diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b9cbf2dfec5e5638822c7aaa4578c98be3802f0a..e0223a8c54b2881404037e5909d556c2b54782dd 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,7 +1,7 @@
 workflow:
   rules:
     - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
-    - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"'
+    - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_REF_PROTECTED != "true"'
       when: never
     - when: always
 
@@ -10,7 +10,7 @@ stages:
   - test
   - check
   - deploy
-  - post-deploy
+  - smoketest
 
 default:
   tags:
@@ -36,16 +36,23 @@ default:
     - echo "{\"auths\":{\"${CR_HOST}\":{\"auth\":\"$(printf "%s:%s" "${CR_USER}" "${CR_PW}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
     - >
       if [ $IMAGE_TAG ]; then
-        KANIKO_D="$KANIKO_D -d $CR_HOST/$CR_ORG/$IMAGE_NAME:$CI_COMMIT_TAG"
-      elif [ $CI_COMMIT_TAG ]; then
         KANIKO_D="$KANIKO_D -d $CR_HOST/$CR_ORG/$IMAGE_NAME:$IMAGE_TAG"
+        export PUBLISHED_IMAGE_TAG=$IMAGE_TAG
+      elif [ $CI_COMMIT_TAG ]; then
+        KANIKO_D="$KANIKO_D -d $CR_HOST/$CR_ORG/$IMAGE_NAME:$CI_COMMIT_TAG"
+        export PUBLISHED_IMAGE_TAG=$CI_COMMIT_TAG
       else
         DOCKER_TAG_NAME=$(echo $CI_COMMIT_REF_SLUG- | sed 's/^master-$//')
         KANIKO_D="$KANIKO_D -d $CR_HOST/$CR_ORG/$IMAGE_NAME:${DOCKER_TAG_NAME}latest"
         KANIKO_D="$KANIKO_D -d $CR_HOST/$CR_ORG/$IMAGE_NAME:$DOCKER_TAG_NAME$CI_COMMIT_SHORT_SHA"
+        export PUBLISHED_IMAGE_TAG=$DOCKER_TAG_NAME$CI_COMMIT_SHORT_SHA
       fi
     - "[ $DOCKERFILE ] && KANIKO_DOCKERFILE=\"--dockerfile $DOCKERFILE\""
     - /kaniko/executor --context `pwd`/$CONTEXT $KANIKO_DOCKERFILE $KANIKO_D
+    - echo "PUBLISHED_IMAGE_TAG=$PUBLISHED_IMAGE_TAG" >> $CI_PROJECT_DIR/build.env
+  artifacts:
+    reports:
+      dotenv: build.env
 
 
 # Theodolite Docs
@@ -80,26 +87,37 @@ test-docs-links:
     - build-docs
   script: bundle exec htmlproofer --assume-extension --allow_hash_href ./_site
 
+build-docs-crds:
+  stage: build
+  image:
+    name: ghcr.io/fybrik/crdoc:0.6.1
+    entrypoint: [""]
+  script: /crdoc --resources theodolite/crd/ --template docs/api-reference/crds.tmpl --output docs/api-reference/crds.ref.md
+  artifacts:
+    paths:
+      - docs/api-reference/crds.ref.md
+    expire_in: 1 week
+  rules:
+    - changes:
+      - docs/api-reference/crds.tmpl
+      - theodolite/crd/**/*
+    - when: manual
+      allow_failure: true
+
 test-docs-crds-regression:
   stage: test
-  image: golang
+  needs:
+    - build-docs-crds
+  image: alpine:3.15
   before_script:
     - cd docs
-    - go install fybrik.io/crdoc@latest
   script:
-    - crdoc --resources ../theodolite/crd/ --template api-reference/crds.tmpl  --output api-reference/crds.ref.md
     - cmp api-reference/crds.md api-reference/crds.ref.md
   artifacts:
     when: on_failure
     paths:
       - docs/api-reference/crds.ref.md
     expire_in: 1 week
-  rules:
-    - changes:
-      - docs/api-reference/crds.tmpl
-      - theodolite/crd/**/*
-    - when: manual
-      allow_failure: true
 
 
 # Theodolite Helm Chart
@@ -111,9 +129,14 @@ lint-helm:
     name: alpine/helm:3.5.2
     entrypoint: [""]
   script: helm lint helm/
+  rules:
+  - changes:
+    - helm/**/*
+  - when: manual
+    allow_failure: true
 
 test-helm:
-  stage: post-deploy
+  stage: smoketest
   extends: .dind
   needs:
     - lint-helm
@@ -313,6 +336,34 @@ deploy-uc4-flink:
     JAVA_PROJECT_NAME: "uc4-flink"
     JAVA_PROJECT_DEPS: "flink-commons"
 
+deploy-uc1-hazelcastjet:
+  extends: .deploy-benchmarks
+  variables:
+    IMAGE_NAME: "theodolite-uc1-hazelcastjet"
+    JAVA_PROJECT_NAME: "uc1-hazelcastjet"
+    JAVA_PROJECT_DEPS: "hazelcastjet-commons"
+
+deploy-uc2-hazelcastjet:
+  extends: .deploy-benchmarks
+  variables:
+    IMAGE_NAME: "theodolite-uc2-hazelcastjet"
+    JAVA_PROJECT_NAME: "uc2-hazelcastjet"
+    JAVA_PROJECT_DEPS: "hazelcastjet-commons"
+
+deploy-uc3-hazelcastjet:
+  extends: .deploy-benchmarks
+  variables:
+    IMAGE_NAME: "theodolite-uc3-hazelcastjet"
+    JAVA_PROJECT_NAME: "uc3-hazelcastjet"
+    JAVA_PROJECT_DEPS: "hazelcastjet-commons"
+
+deploy-uc4-hazelcastjet:
+  extends: .deploy-benchmarks
+  variables:
+    IMAGE_NAME: "theodolite-uc4-hazelcastjet"
+    JAVA_PROJECT_NAME: "uc4-hazelcastjet"
+    JAVA_PROJECT_DEPS: "hazelcastjet-commons"
+
 deploy-uc1-beam-flink:
   extends: .deploy-benchmarks
   variables:
@@ -396,7 +447,209 @@ deploy-uc4-load-generator:
     IMAGE_NAME: "theodolite-uc4-workload-generator"
     JAVA_PROJECT_NAME: "uc4-load-generator"
     JAVA_PROJECT_DEPS: "load-generator-commons"
-      
+
+deploy-http-bridge:
+  extends: .deploy-benchmarks
+  variables:
+    IMAGE_NAME: "theodolite-http-bridge"
+    JAVA_PROJECT_NAME: "http-bridge"
+    JAVA_PROJECT_DEPS: "load-generator-commons"
+
+.smoketest-benchmarks:
+  stage: smoketest
+  extends:
+    - .dind
+  image: ghcr.io/cau-se/theodolite-build-docker-compose-jq:20.10.12
+  before_script:
+    - cd theodolite-benchmarks/docker-test
+  # variables:
+  #   TEST_LOG_FILE: "test.log"
+  script:
+    - export THEODOLITE_TAG=$PUBLISHED_IMAGE_TAG
+    - ./smoketest-runner.sh ./$DOCKER_COMPOSE_DIR
+    # - cat test.log
+  after_script:
+    - cd ./$DOCKER_COMPOSE_DIR
+    - docker-compose down
+  rules:
+    - changes:
+      - theodolite-benchmarks/*
+      - theodolite-benchmarks/{$JAVA_PROJECT_DEPS}/**/*
+      if: "$CR_HOST && $CR_ORG && $CR_USER && $CR_PW && $DOCKER_COMPOSE_DIR && $JAVA_PROJECT_DEPS"
+    - if: "$CR_HOST && $CR_ORG && $CR_USER && $CR_PW && $DOCKER_COMPOSE_DIR && $JAVA_PROJECT_DEPS"
+      when: manual
+      allow_failure: true
+
+smoketest-uc1-kstreams:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc1-kstreams
+    - deploy-uc1-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc1-kstreams"
+    JAVA_PROJECT_DEPS: "uc1-kstreams,kstreams-commons,uc1-load-generator,load-generator-commons"
+
+smoketest-uc1-flink:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc1-flink
+    - deploy-uc1-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc1-flink"
+    JAVA_PROJECT_DEPS: "uc1-flink,flink-commons,uc1-load-generator,load-generator-commons"
+
+smoketest-uc1-beam-flink:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc1-beam-flink
+    - deploy-uc1-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc1-beam-flink"
+    JAVA_PROJECT_DEPS: "uc1-beam-flink,uc1-beam,beam-commons,uc1-load-generator,load-generator-commons"
+
+smoketest-uc1-beam-samza:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc1-beam-samza
+    - deploy-uc1-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc1-beam-samza"
+    JAVA_PROJECT_DEPS: "uc1-beam-samza,uc1-beam,beam-commons,uc1-load-generator,load-generator-commons"
+
+smoketest-uc1-hazelcastjet:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc1-hazelcastjet
+    - deploy-uc1-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc1-hazelcastjet"
+    JAVA_PROJECT_DEPS: "uc1-hazelcastjet,hazelcastjet-commons,uc1-load-generator,load-generator-commons"
+
+smoketest-uc2-kstreams:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc2-kstreams
+    - deploy-uc2-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc2-kstreams"
+    JAVA_PROJECT_DEPS: "uc2-kstreams,kstreams-commons,uc2-load-generator,load-generator-commons"
+
+smoketest-uc2-flink:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc2-flink
+    - deploy-uc2-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc2-flink"
+    JAVA_PROJECT_DEPS: "uc2-flink,flink-commons,uc2-load-generator,load-generator-commons"
+
+smoketest-uc2-beam-flink:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc2-beam-flink
+    - deploy-uc2-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc2-beam-flink"
+    JAVA_PROJECT_DEPS: "uc2-beam-flink,uc2-beam,beam-commons,uc2-load-generator,load-generator-commons"
+
+smoketest-uc2-beam-samza:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc2-beam-samza
+    - deploy-uc2-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc2-beam-samza"
+    JAVA_PROJECT_DEPS: "uc2-beam-samza,uc2-beam,beam-commons,uc2-load-generator,load-generator-commons"
+
+smoketest-uc2-hazelcastjet:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc2-hazelcastjet
+    - deploy-uc2-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc2-hazelcastjet"
+    JAVA_PROJECT_DEPS: "uc2-hazelcastjet,hazelcastjet-commons,uc2-load-generator,load-generator-commons"
+
+smoketest-uc3-kstreams:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc3-kstreams
+    - deploy-uc3-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc3-kstreams"
+    JAVA_PROJECT_DEPS: "uc3-kstreams,kstreams-commons,uc3-load-generator,load-generator-commons"
+
+smoketest-uc3-beam-flink:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc3-beam-flink
+    - deploy-uc3-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc3-beam-flink"
+    JAVA_PROJECT_DEPS: "uc3-beam-flink,uc3-beam,beam-commons,uc3-load-generator,load-generator-commons"
+
+smoketest-uc3-beam-samza:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc3-beam-samza
+    - deploy-uc3-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc3-beam-samza"
+    JAVA_PROJECT_DEPS: "uc3-beam-samza,uc3-beam,beam-commons,uc3-load-generator,load-generator-commons"
+
+smoketest-uc3-hazelcastjet:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc3-hazelcastjet
+    - deploy-uc3-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc3-hazelcastjet"
+    JAVA_PROJECT_DEPS: "uc3-hazelcastjet,hazelcastjet-commons,uc3-load-generator,load-generator-commons"
+
+smoketest-uc4-kstreams:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc4-kstreams
+    - deploy-uc4-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc4-kstreams"
+    JAVA_PROJECT_DEPS: "uc4-kstreams,kstreams-commons,uc4-load-generator,load-generator-commons"
+
+smoketest-uc4-flink:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc4-flink
+    - deploy-uc4-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc4-flink"
+    JAVA_PROJECT_DEPS: "uc4-flink,flink-commons,uc4-load-generator,load-generator-commons"
+
+smoketest-uc4-beam-flink:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc4-beam-flink
+    - deploy-uc4-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc4-beam-flink"
+    JAVA_PROJECT_DEPS: "uc4-beam-flink,uc4-beam,beam-commons,uc4-load-generator,load-generator-commons"
+
+smoketest-uc4-beam-samza:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc4-beam-samza
+    - deploy-uc4-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc4-beam-samza"
+    JAVA_PROJECT_DEPS: "uc4-beam-samza,uc4-beam,beam-commons,uc4-load-generator,load-generator-commons"
+
+smoketest-uc4-hazelcastjet:
+  extends: .smoketest-benchmarks
+  needs:
+    - deploy-uc4-hazelcastjet
+    - deploy-uc4-load-generator
+  variables:
+    DOCKER_COMPOSE_DIR: "uc4-hazelcastjet"
+    JAVA_PROJECT_DEPS: "uc4-hazelcastjet,hazelcastjet-commons,uc4-load-generator,load-generator-commons"
 
 # Theodolite Framework
 
@@ -413,6 +666,11 @@ deploy-uc4-load-generator:
   before_script:
     - export GRADLE_USER_HOME=`pwd`/.gradle
     - cd theodolite
+  rules:
+    - changes:
+      - theodolite/**/*
+    - when: manual
+      allow_failure: true
 
 build-theodolite-jvm:
   stage: build
diff --git a/CITATION.cff b/CITATION.cff
index 04640de442f4458b09e11ce3d2939c850f594556..160146c844b1d128299617ae8d93ac4af77e4ca0 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -1,6 +1,6 @@
 cff-version: "1.1.0"
 message: "If you use Theodolite, please cite it using these metadata."
-authors: 
+authors:
   - family-names: Henning
     given-names: "Sören"
     orcid: "https://orcid.org/0000-0001-6912-2549"
@@ -8,13 +8,13 @@ authors:
     given-names: Wilhelm
     orcid: "https://orcid.org/0000-0001-6625-4335"
 title: Theodolite
-version: "0.6.3"
+version: "0.7.0"
 repository-code: "https://github.com/cau-se/theodolite"
 license: "Apache-2.0"
 doi: "10.1016/j.bdr.2021.100209"
 preferred-citation:
   type: article
-  authors: 
+  authors:
     - family-names: Henning
       given-names: "Sören"
       orcid: "https://orcid.org/0000-0001-6912-2549"
diff --git a/codemeta.json b/codemeta.json
index 832b570681afb143978698fd47dad5d2835c700b..fa2eb23a956d9ad2525beee1b5ca343845c38d2d 100644
--- a/codemeta.json
+++ b/codemeta.json
@@ -5,10 +5,10 @@
     "codeRepository": "https://github.com/cau-se/theodolite",
     "dateCreated": "2020-03-13",
     "datePublished": "2020-07-27",
-    "dateModified": "2022-01-24",
+    "dateModified": "2022-05-11",
     "downloadUrl": "https://github.com/cau-se/theodolite/releases",
     "name": "Theodolite",
-    "version": "0.6.3",
+    "version": "0.7.0",
     "description": "Theodolite is a framework for benchmarking the horizontal and vertical scalability of cloud-native applications.",
     "developmentStatus": "active",
     "relatedLink": [
diff --git a/docs/Gemfile b/docs/Gemfile
index c9ce8dff9c02691c4a6a3be9e94341745378fb0b..b2bab9c1cd6c4591d474c8545e459276692ab487 100644
--- a/docs/Gemfile
+++ b/docs/Gemfile
@@ -9,11 +9,11 @@ source "https://rubygems.org"
 # Happy Jekylling!
 #gem "jekyll", "~> 4.2.0"
 # This is the default theme for new Jekyll sites. You may change this to anything you like.
-gem "minima", "~> 2.5"
+#gem "minima", "~> 2.5"
 # If you want to use GitHub Pages, remove the "gem "jekyll"" above and
 # uncomment the line below. To upgrade, run `bundle update github-pages`.
-# gem "github-pages", group: :jekyll_plugins
-gem "github-pages", "~> 215", group: :jekyll_plugins
+gem "github-pages", group: :jekyll_plugins
+#gem "github-pages", "~> 226", group: :jekyll_plugins
 # If you have any plugins, put them here!
 #group :jekyll_plugins do
   #gem "jekyll-feed", "~> 0.12"
diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock
index 34ed67d70b1212b14bbf47a2062cf1138817df63..4acb2ba79d5cde699cf9dd4d379bf17c3c93e068 100644
--- a/docs/Gemfile.lock
+++ b/docs/Gemfile.lock
@@ -1,7 +1,7 @@
 GEM
   remote: https://rubygems.org/
   specs:
-    activesupport (6.0.4)
+    activesupport (6.0.4.8)
       concurrent-ruby (~> 1.0, >= 1.0.2)
       i18n (>= 0.7, < 2)
       minitest (~> 5.1)
@@ -14,44 +14,54 @@ GEM
       execjs
     coffee-script-source (1.11.1)
     colorator (1.1.0)
-    commonmarker (0.17.13)
-      ruby-enum (~> 0.5)
-    concurrent-ruby (1.1.9)
-    dnsruby (1.61.7)
+    commonmarker (0.23.4)
+    concurrent-ruby (1.1.10)
+    dnsruby (1.61.9)
       simpleidn (~> 0.1)
-    em-websocket (0.5.2)
+    em-websocket (0.5.3)
       eventmachine (>= 0.12.9)
-      http_parser.rb (~> 0.6.0)
-    ethon (0.14.0)
+      http_parser.rb (~> 0)
+    ethon (0.15.0)
       ffi (>= 1.15.0)
     eventmachine (1.2.7)
     execjs (2.8.1)
-    faraday (1.4.3)
+    faraday (1.10.0)
       faraday-em_http (~> 1.0)
       faraday-em_synchrony (~> 1.0)
       faraday-excon (~> 1.1)
+      faraday-httpclient (~> 1.0)
+      faraday-multipart (~> 1.0)
       faraday-net_http (~> 1.0)
-      faraday-net_http_persistent (~> 1.1)
-      multipart-post (>= 1.2, < 3)
+      faraday-net_http_persistent (~> 1.0)
+      faraday-patron (~> 1.0)
+      faraday-rack (~> 1.0)
+      faraday-retry (~> 1.0)
       ruby2_keywords (>= 0.0.4)
     faraday-em_http (1.0.0)
     faraday-em_synchrony (1.0.0)
     faraday-excon (1.1.0)
+    faraday-httpclient (1.0.1)
+    faraday-multipart (1.0.3)
+      multipart-post (>= 1.2, < 3)
     faraday-net_http (1.0.1)
-    faraday-net_http_persistent (1.1.0)
-    ffi (1.15.3)
+    faraday-net_http_persistent (1.2.0)
+    faraday-patron (1.0.0)
+    faraday-rack (1.0.0)
+    faraday-retry (1.0.3)
+    ffi (1.15.5)
     forwardable-extended (2.6.0)
     gemoji (3.0.1)
-    github-pages (215)
-      github-pages-health-check (= 1.17.2)
-      jekyll (= 3.9.0)
+    github-pages (226)
+      github-pages-health-check (= 1.17.9)
+      jekyll (= 3.9.2)
       jekyll-avatar (= 0.7.0)
       jekyll-coffeescript (= 1.1.1)
-      jekyll-commonmark-ghpages (= 0.1.6)
+      jekyll-commonmark-ghpages (= 0.2.0)
       jekyll-default-layout (= 0.1.4)
       jekyll-feed (= 0.15.1)
       jekyll-gist (= 1.5.0)
       jekyll-github-metadata (= 2.13.0)
+      jekyll-include-cache (= 0.2.1)
       jekyll-mentions (= 1.6.0)
       jekyll-optional-front-matter (= 0.3.2)
       jekyll-paginate (= 1.1.0)
@@ -60,53 +70,53 @@ GEM
       jekyll-relative-links (= 0.6.1)
       jekyll-remote-theme (= 0.4.3)
       jekyll-sass-converter (= 1.5.2)
-      jekyll-seo-tag (= 2.7.1)
+      jekyll-seo-tag (= 2.8.0)
       jekyll-sitemap (= 1.4.0)
       jekyll-swiss (= 1.0.0)
-      jekyll-theme-architect (= 0.1.1)
-      jekyll-theme-cayman (= 0.1.1)
-      jekyll-theme-dinky (= 0.1.1)
-      jekyll-theme-hacker (= 0.1.2)
-      jekyll-theme-leap-day (= 0.1.1)
-      jekyll-theme-merlot (= 0.1.1)
-      jekyll-theme-midnight (= 0.1.1)
-      jekyll-theme-minimal (= 0.1.1)
-      jekyll-theme-modernist (= 0.1.1)
-      jekyll-theme-primer (= 0.5.4)
-      jekyll-theme-slate (= 0.1.1)
-      jekyll-theme-tactile (= 0.1.1)
-      jekyll-theme-time-machine (= 0.1.1)
+      jekyll-theme-architect (= 0.2.0)
+      jekyll-theme-cayman (= 0.2.0)
+      jekyll-theme-dinky (= 0.2.0)
+      jekyll-theme-hacker (= 0.2.0)
+      jekyll-theme-leap-day (= 0.2.0)
+      jekyll-theme-merlot (= 0.2.0)
+      jekyll-theme-midnight (= 0.2.0)
+      jekyll-theme-minimal (= 0.2.0)
+      jekyll-theme-modernist (= 0.2.0)
+      jekyll-theme-primer (= 0.6.0)
+      jekyll-theme-slate (= 0.2.0)
+      jekyll-theme-tactile (= 0.2.0)
+      jekyll-theme-time-machine (= 0.2.0)
       jekyll-titles-from-headings (= 0.5.3)
       jemoji (= 0.12.0)
-      kramdown (= 2.3.1)
+      kramdown (= 2.3.2)
       kramdown-parser-gfm (= 1.1.0)
       liquid (= 4.0.3)
       mercenary (~> 0.3)
       minima (= 2.5.1)
-      nokogiri (>= 1.10.4, < 2.0)
+      nokogiri (>= 1.13.4, < 2.0)
       rouge (= 3.26.0)
       terminal-table (~> 1.4)
-    github-pages-health-check (1.17.2)
+    github-pages-health-check (1.17.9)
       addressable (~> 2.3)
       dnsruby (~> 1.60)
       octokit (~> 4.0)
-      public_suffix (>= 2.0.2, < 5.0)
+      public_suffix (>= 3.0, < 5.0)
       typhoeus (~> 1.3)
-    html-pipeline (2.14.0)
+    html-pipeline (2.14.1)
       activesupport (>= 2)
       nokogiri (>= 1.4)
-    html-proofer (3.19.2)
+    html-proofer (3.19.3)
       addressable (~> 2.3)
       mercenary (~> 0.3)
-      nokogumbo (~> 2.0)
+      nokogiri (~> 1.12)
       parallel (~> 1.3)
       rainbow (~> 3.0)
       typhoeus (~> 1.3)
       yell (~> 2.0)
-    http_parser.rb (0.6.0)
+    http_parser.rb (0.8.0)
     i18n (0.9.5)
       concurrent-ruby (~> 1.0)
-    jekyll (3.9.0)
+    jekyll (3.9.2)
       addressable (~> 2.4)
       colorator (~> 1.0)
       em-websocket (~> 0.5)
@@ -124,12 +134,12 @@ GEM
     jekyll-coffeescript (1.1.1)
       coffee-script (~> 2.2)
       coffee-script-source (~> 1.11.1)
-    jekyll-commonmark (1.3.1)
-      commonmarker (~> 0.14)
-      jekyll (>= 3.7, < 5.0)
-    jekyll-commonmark-ghpages (0.1.6)
-      commonmarker (~> 0.17.6)
-      jekyll-commonmark (~> 1.2)
+    jekyll-commonmark (1.4.0)
+      commonmarker (~> 0.22)
+    jekyll-commonmark-ghpages (0.2.0)
+      commonmarker (~> 0.23.4)
+      jekyll (~> 3.9.0)
+      jekyll-commonmark (~> 1.4.0)
       rouge (>= 2.0, < 4.0)
     jekyll-default-layout (0.1.4)
       jekyll (~> 3.0)
@@ -140,6 +150,8 @@ GEM
     jekyll-github-metadata (2.13.0)
       jekyll (>= 3.4, < 5.0)
       octokit (~> 4.0, != 4.4.0)
+    jekyll-include-cache (0.2.1)
+      jekyll (>= 3.7, < 5.0)
     jekyll-mentions (1.6.0)
       html-pipeline (~> 2.3)
       jekyll (>= 3.7, < 5.0)
@@ -159,50 +171,50 @@ GEM
       rubyzip (>= 1.3.0, < 3.0)
     jekyll-sass-converter (1.5.2)
       sass (~> 3.4)
-    jekyll-seo-tag (2.7.1)
+    jekyll-seo-tag (2.8.0)
       jekyll (>= 3.8, < 5.0)
     jekyll-sitemap (1.4.0)
       jekyll (>= 3.7, < 5.0)
     jekyll-swiss (1.0.0)
-    jekyll-theme-architect (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-architect (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-cayman (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-cayman (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-dinky (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-dinky (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-hacker (0.1.2)
+    jekyll-theme-hacker (0.2.0)
       jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-leap-day (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-leap-day (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-merlot (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-merlot (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-midnight (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-midnight (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-minimal (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-minimal (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-modernist (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-modernist (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-primer (0.5.4)
+    jekyll-theme-primer (0.6.0)
       jekyll (> 3.5, < 5.0)
       jekyll-github-metadata (~> 2.9)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-slate (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-slate (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-tactile (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-tactile (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-time-machine (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-time-machine (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
     jekyll-titles-from-headings (0.5.3)
       jekyll (>= 3.3, < 5.0)
@@ -212,12 +224,12 @@ GEM
       gemoji (~> 3.0)
       html-pipeline (~> 2.2)
       jekyll (>= 3.0, < 5.0)
-    kramdown (2.3.1)
+    kramdown (2.3.2)
       rexml
     kramdown-parser-gfm (1.1.0)
       kramdown (~> 2.0)
     liquid (4.0.3)
-    listen (3.5.1)
+    listen (3.7.1)
       rb-fsevent (~> 0.10, >= 0.10.3)
       rb-inotify (~> 0.9, >= 0.9.10)
     mercenary (0.3.6)
@@ -225,30 +237,26 @@ GEM
       jekyll (>= 3.5, < 5.0)
       jekyll-feed (~> 0.9)
       jekyll-seo-tag (~> 2.1)
-    minitest (5.14.4)
+    minitest (5.15.0)
     multipart-post (2.1.1)
-    nokogiri (1.13.0-x86_64-linux)
+    nokogiri (1.13.6-x86_64-linux)
       racc (~> 1.4)
-    nokogumbo (2.0.5)
-      nokogiri (~> 1.8, >= 1.8.4)
-    octokit (4.21.0)
+    octokit (4.22.0)
       faraday (>= 0.9)
       sawyer (~> 0.8.0, >= 0.5.3)
-    parallel (1.21.0)
+    parallel (1.22.1)
     pathutil (0.16.2)
       forwardable-extended (~> 2.6)
-    public_suffix (4.0.6)
+    public_suffix (4.0.7)
     racc (1.6.0)
-    rainbow (3.0.0)
-    rb-fsevent (0.11.0)
+    rainbow (3.1.1)
+    rb-fsevent (0.11.1)
     rb-inotify (0.10.1)
       ffi (~> 1.0)
     rexml (3.2.5)
     rouge (3.26.0)
-    ruby-enum (0.9.0)
-      i18n
-    ruby2_keywords (0.0.4)
-    rubyzip (2.3.0)
+    ruby2_keywords (0.0.5)
+    rubyzip (2.3.2)
     safe_yaml (1.0.5)
     sass (3.7.4)
       sass-listen (~> 4.0.0)
@@ -269,19 +277,17 @@ GEM
       thread_safe (~> 0.1)
     unf (0.1.4)
       unf_ext
-    unf_ext (0.0.7.7)
-    unicode-display_width (1.7.0)
+    unf_ext (0.0.8.1)
+    unicode-display_width (1.8.0)
     yell (2.2.2)
-    zeitwerk (2.4.2)
+    zeitwerk (2.5.4)
 
 PLATFORMS
   x86_64-linux
-  x86_64-linux-musl
 
 DEPENDENCIES
-  github-pages (~> 215)
+  github-pages
   html-proofer
-  minima (~> 2.5)
   tzinfo (~> 1.2)
   tzinfo-data
   wdm (~> 0.1.1)
diff --git a/docs/README.md b/docs/README.md
index 52b5311295e5a96721d9aa42f7e9c319da06960c..a19f94305dfdcb1de7c46da98afbb52b28a6bfa0 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -39,5 +39,5 @@ crdoc --resources ../theodolite/crd/ --template api-reference/crds.tmpl  --outpu
 With the following command, crdoc is executed in Docker:
 
 ```sh
-docker run --rm -v "`pwd`/../theodolite/crd/":/crd -u $UID -v "`pwd`/api-reference":/api-reference ghcr.io/fybrik/crdoc:0.6.0 --resources /crd/ --template /api-reference/crds.tmpl --output /api-reference/crds.md
+docker run --rm -v "`pwd`/../theodolite/crd/":/crd -v "`pwd`/api-reference":/api-reference ghcr.io/fybrik/crdoc:0.6.1 --resources /crd/ --template /api-reference/crds.tmpl --output /api-reference/crds.md
 ```
diff --git a/docs/_config.yml b/docs/_config.yml
index 0d2a1aa774a83347c80b538a97d5dbfa1b7639b3..95cc5a635494842f1894c572cb117aafb3bb6810 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -3,7 +3,7 @@ description: >-
   Theodolite is a framework for benchmarking the horizontal and vertical
   scalability of cloud-native applications.
 
-remote_theme: pmarsceill/just-the-docs
+remote_theme: just-the-docs/just-the-docs
 aux_links:
     "Theodolite on GitHub":
       - "//github.com/cau-se/theodolite"
diff --git a/docs/api-reference/crds.md b/docs/api-reference/crds.md
index fb3f02ac941870dd085d06027d972e6003c7aadb..f0962d47400dfb85f8f9a2b695fec49cc45fe6e8 100644
--- a/docs/api-reference/crds.md
+++ b/docs/api-reference/crds.md
@@ -114,6 +114,13 @@ Resource Types:
           A list of resource types that can be scaled for this `benchmark` resource. For each resource type the concrete values are defined in the `execution` object.<br/>
         </td>
         <td>true</td>
+      </tr><tr>
+        <td><b><a href="#benchmarkspecslosindex">slos</a></b></td>
+        <td>[]object</td>
+        <td>
+          List of resource values for the specified resource type.<br/>
+        </td>
+        <td>true</td>
       </tr><tr>
         <td><b><a href="#benchmarkspecsut">sut</a></b></td>
         <td>object</td>
@@ -146,6 +153,15 @@ Resource Types:
             <i>Default</i>: <br/>
         </td>
         <td>false</td>
+      </tr><tr>
+        <td><b>waitForResourcesEnabled</b></td>
+        <td>boolean</td>
+        <td>
+          If true, Theodolite waits to create the resource for the SUT until the infrastructure resources are ready, and analogously, Theodolite waits to create the load-gen resource until the resources of the SUT are ready.<br/>
+          <br/>
+            <i>Default</i>: false<br/>
+        </td>
+        <td>false</td>
       </tr></tbody>
 </table>
 
@@ -727,6 +743,63 @@ The fileSystem resourceSet loads the Kubernetes manifests from the filesystem.
 </table>
 
 
+### benchmark.spec.slos[index]
+<sup><sup>[↩ Parent](#benchmarkspec)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>name</b></td>
+        <td>string</td>
+        <td>
+          The name of the SLO.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>offset</b></td>
+        <td>integer</td>
+        <td>
+          Hours by which the start and end timestamp will be shifted (for different timezones).<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>prometheusUrl</b></td>
+        <td>string</td>
+        <td>
+          Connection string for Promehteus.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>sloType</b></td>
+        <td>string</td>
+        <td>
+          The type of the SLO. It must match 'lag trend'.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>properties</b></td>
+        <td>map[string]string</td>
+        <td>
+          (Optional) SLO specific additional arguments.<br/>
+          <br/>
+            <i>Default</i>: map[]<br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
 ### benchmark.spec.sut
 <sup><sup>[↩ Parent](#benchmarkspec)</sup></sup>
 
@@ -1765,7 +1838,7 @@ Contains the Kafka configuration.
         </td>
         <td>true</td>
       </tr><tr>
-        <td><b><a href="#executionspecload">load</a></b></td>
+        <td><b><a href="#executionspecloads">loads</a></b></td>
         <td>object</td>
         <td>
           Specifies the load values that are benchmarked.<br/>
@@ -1778,13 +1851,6 @@ Contains the Kafka configuration.
           Specifies the scaling resource that is benchmarked.<br/>
         </td>
         <td>true</td>
-      </tr><tr>
-        <td><b><a href="#executionspecslosindex">slos</a></b></td>
-        <td>[]object</td>
-        <td>
-          List of resource values for the specified resource type.<br/>
-        </td>
-        <td>true</td>
       </tr><tr>
         <td><b>name</b></td>
         <td>string</td>
@@ -1794,6 +1860,13 @@ Contains the Kafka configuration.
             <i>Default</i>: <br/>
         </td>
         <td>false</td>
+      </tr><tr>
+        <td><b><a href="#executionspecslosindex">slos</a></b></td>
+        <td>[]object</td>
+        <td>
+          List of SLOs with their properties, which differ from the benchmark definition.<br/>
+        </td>
+        <td>false</td>
       </tr></tbody>
 </table>
 
@@ -1906,35 +1979,83 @@ Defines the overall parameter for the execution.
         <td><b>repetitions</b></td>
         <td>integer</td>
         <td>
-          Numper of repititions for each experiments.<br/>
+          Number of repititions for each experiment.<br/>
         </td>
         <td>true</td>
       </tr><tr>
-        <td><b>restrictions</b></td>
-        <td>[]string</td>
+        <td><b><a href="#executionspecexecutionstrategy">strategy</a></b></td>
+        <td>object</td>
         <td>
-          List of restriction strategys used to delimit the search space.<br/>
+          Defines the used strategy for the execution, either 'LinearSearch', 'BinarySearch' or 'InitialGuessSearch'.<br/>
         </td>
         <td>true</td>
       </tr><tr>
-        <td><b>strategy</b></td>
+        <td><b>loadGenerationDelay</b></td>
+        <td>integer</td>
+        <td>
+          Seconds to wait between the start of the SUT and the load generator.<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>metric</b></td>
+        <td>string</td>
+        <td>
+          <br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### execution.spec.execution.strategy
+<sup><sup>[↩ Parent](#executionspecexecution)</sup></sup>
+
+
+
+Defines the used strategy for the execution, either 'LinearSearch', 'BinarySearch' or 'InitialGuessSearch'.
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>name</b></td>
         <td>string</td>
         <td>
-          Defines the used strategy for the execution, either 'LinearSearch' or 'BinarySearch'<br/>
+          <br/>
         </td>
         <td>true</td>
       </tr><tr>
-        <td><b>loadGenerationDelay</b></td>
-        <td>integer</td>
+        <td><b>guessStrategy</b></td>
+        <td>string</td>
         <td>
-          Seconds to wait between the start of the SUT and the load generator.<br/>
+          <br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>restrictions</b></td>
+        <td>[]string</td>
+        <td>
+          List of restriction strategies used to delimit the search space.<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>searchStrategy</b></td>
+        <td>string</td>
+        <td>
+          <br/>
         </td>
         <td>false</td>
       </tr></tbody>
 </table>
 
 
-### execution.spec.load
+### execution.spec.loads
 <sup><sup>[↩ Parent](#executionspec)</sup></sup>
 
 
@@ -2019,24 +2140,10 @@ Specifies the scaling resource that is benchmarked.
         </tr>
     </thead>
     <tbody><tr>
-        <td><b>offset</b></td>
-        <td>integer</td>
-        <td>
-          Hours by which the start and end timestamp will be shifted (for different timezones).<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>prometheusUrl</b></td>
-        <td>string</td>
-        <td>
-          Connection string for Promehteus.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>sloType</b></td>
+        <td><b>name</b></td>
         <td>string</td>
         <td>
-          The type of the SLO. It must match 'lag trend'.<br/>
+          The name of the SLO. It must match a SLO specified in the Benchmark.<br/>
         </td>
         <td>true</td>
       </tr><tr>
@@ -2047,7 +2154,7 @@ Specifies the scaling resource that is benchmarked.
           <br/>
             <i>Default</i>: map[]<br/>
         </td>
-        <td>false</td>
+        <td>true</td>
       </tr></tbody>
 </table>
 
diff --git a/docs/api-reference/patchers.md b/docs/api-reference/patchers.md
index 77f937e38f6a0ee4084cb0ad5b5838718eabff10..bea63ccd23decef5654f257221ce0358b4f68e45 100644
--- a/docs/api-reference/patchers.md
+++ b/docs/api-reference/patchers.md
@@ -53,6 +53,27 @@ Patchers can be seen as functions which take a value as input and modify a Kuber
   * **resource**: "uc1-kstreams-deployment.yaml"
   * **example value**: "random-scheduler"
 
+* **LabelPatcher**: Changes the label of a Kubernetes Deployment or StatefulSet. The patched field is: `metadata.labels`
+  * **type**: "LabelPatcher"
+  * **resource**: "uc1-kstreams-deployment.yaml"
+  * **properties**:
+    * variableName: "app"
+  * **example value**: "theodolite-sut"
+
+* **MatchLabelPatcher**: Changes the match labels of a Kubernetes Deployment or StatefulSet. The patched field is: `spec.selector.matchLabels`
+  * **type**: "MatchLabelPatcher"
+  * **resource**: "uc1-kstreams-deployment.yaml"
+  * **properties**:
+    * variableName: "app"
+  * **example value**: "theodolite-sut"
+
+* **TemplateLabelPatcher**: Changes the template labels of a Kubernetes Deployment or StatefulSet. The patched field is: `spec.template.metadata.labels`
+  * **type**: "MatchLabelPatcher"
+  * **resource**: "uc1-kstreams-deployment.yaml"
+  * **properties**:
+    * variableName: "app"
+  * **example value**: "theodolite-sut"
+
 * **ImagePatcher**: Changes the image of a Kubernetes resource. **Currently not fully implemented.**
   * **type**: "ImagePatcher"
   * **resource**: "uc1-kstreams-deployment.yaml"
diff --git a/docs/creating-a-benchmark.md b/docs/creating-a-benchmark.md
index fde8ba0759407ddea8befc18e244784a9ba34c1f..b4602d6f7fd209b5851a9a9db128dfce6369b2a4 100644
--- a/docs/creating-a-benchmark.md
+++ b/docs/creating-a-benchmark.md
@@ -42,7 +42,7 @@ spec:
           properties:
             loadGenMaxRecords: "150000"
   kafkaConfig:
-    bootstrapServer: "theodolite-cp-kafka:9092"
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
     topics:
       - name: "input"
         numPartitions: 40
@@ -54,7 +54,7 @@ spec:
 
 ## System under Test (SUT), Load Generator and Infrastructure
 
-In Thedolite, the system under test (SUT), the load generator as well as additional infrastructure (e.g., a middleware) are described by Kubernetes resources files.
+In Theodolite, the system under test (SUT), the load generator as well as additional infrastructure (e.g., a middleware) are described by Kubernetes resources files.
 All resources defined for the SUT and the load generator are started and stopped for each SLO experiment, with SUT resources being started before the load generator.
 Infrastructure resources live over the entire duration of a benchmark run. They avoid time-consuming recreation of software components like middlewares, but should be used with caution to not let previous SLO experiments influence latte ones.
 
@@ -91,10 +91,37 @@ filesystem:
   - example-service.yaml
 ```
 
-<!-- ### Before and after actions -->
+### Actions
 
+Sometimes it is not sufficient to just define resources that are created and deleted when running a benchmark. Instead, it might be necessary to define certain actions that will be executed before running or after stopping the benchmark.
 
+Theodolite allows to execute commands on running pods. This is similar to `kubectl exec` or Kubernetes' [container lifecycle handlers](https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/). Theodolite actions can run before (`beforeActions`) or after `afterActions` all `sut`, `loadGenerator` or `infrastructure` resources are deployed.
+For example, the following actions will create a file in a pod with label `app: logger` before the SUT is started and delete if after the SUT is stopped:
 
+ ```yaml
+  sut:
+    resources: # ...
+    beforeActions:
+      - selector:
+          pod:
+            matchLabels:
+              app: logger
+        exec:
+          command: ["touch", "file-used-by-logger.txt"]
+          timeoutSeconds: 90
+    afterActions:
+      - selector:
+          pod:
+            matchLabels:
+              app: logger
+        exec:
+          command: [ "rm", "file-used-by-logger.txt" ]
+          timeoutSeconds: 90
+```
+
+Theodolite checks if all referenced pods are available for the specified actions. That means these pods must either be defined in `infrastructure` or already deployed in the cluster. If not all referenced pods are available, the benchmark will not be set as `Ready`. Consequently, an action cannot be executed on a pod that is defined as an SUT or load generator resource.
+
+*Note: Actions should be used sparingly. While it is possible to define entire benchmarks imperatively as actions, it is considered better practice to define as much as possible using declarative, native Kubernetes resource files.*
 
 <!--
 A Benchmark refers to other Kubernetes resources (e.g., Deployments, Services, ConfigMaps), which describe the system under test, the load generator and infrastructure components such as a middleware used in the benchmark. To manage those resources, Theodolite needs to have access to them. This is done by bundling resources in ConfigMaps.
@@ -116,7 +143,7 @@ If a benchmark is [executed by an Execution](running-benchmarks), these patchers
 ## Kafka Configuration
 
 Theodolite allows to automatically create and remove Kafka topics for each SLO experiment by setting a `kafkaConfig`.
-It `bootstrapServer` needs to point your Kafka cluster and `topics` configures the list of Kafka topics to be created/removed.
+`bootstrapServer` needs to point your Kafka cluster and `topics` configures the list of Kafka topics to be created/removed.
 For each topic, you configure its name, the number of partitions and the replication factor.
 
 With the `removeOnly: True` property, you can also instruct Theodolite to only remove topics and not create them.
diff --git a/docs/drafts/actions.md b/docs/drafts/actions.md
deleted file mode 100644
index 8092fddb088b3fe8fc64f51bff03bb0c6504b74f..0000000000000000000000000000000000000000
--- a/docs/drafts/actions.md
+++ /dev/null
@@ -1,62 +0,0 @@
-## Infrastructure
-The necessary infrastructure for an execution can be defined in the benchmark manifests. The related resources are create *before* an execution is started, and removed *after* an execution is finished.
-
-### Example
-
-```yaml
-  infrastructure:
-    resources:
-      - configMap:
-          name: "example-configmap"
-          files:
-            - "uc1-kstreams-deployment.yaml"
-```
-
-## Action Commands
-Theodolite allows to execute commands on running pods (similar to the `kubectl exec -it <pod-name> -- <command>` command). This commands can be run either before (via so called `beforeActions`) or after (via so called `afterActions`) an experiment is executed.
-
-Theodolite checks if all required pods are available for the specified actions (i.e. the pods must either be defined as infrastructure or already deployed in the cluster). If not all pods/resources are available, the benchmark will not be set as `Ready`. Consequently, an action cannot be executed on a pod that is defined as an SUT or loadGen resource.
-
-### Example
-
-```yaml
-# For the system under test
-  sut:
-    resources: ...
-    beforeActions:
-      - selector:
-          pod:
-            matchLabels:
-              app: busybox1
-        exec:
-          command: ["touch", "test-file-sut"]
-          timeoutSeconds: 90
-    afterActions:
-      - selector:
-          pod:
-            matchLabels:
-              app: busybox1
-        exec:
-          command: [ "touch", "test-file-sut-after" ]
-          timeoutSeconds: 90
-
-# analog, for the load generator
-  loadGenerator:
-    resources: ... 
-    beforeActions:
-      - selector:
-          pod:
-            matchLabels:
-              app: busybox1
-        exec:
-          command: ["touch", "test-file-loadGen"]
-          timeoutSeconds: 90
-    afterActions:
-      - selector:
-          pod:
-            matchLabels:
-              app: busybox1
-        exec:
-          command: [ "touch", "test-file-loadGen-after" ]
-          timeoutSeconds: 90
-```
\ No newline at end of file
diff --git a/docs/index.yaml b/docs/index.yaml
index 509844ab0bc371d29302f90f69e769cd52a8e11b..956bb83b19ebbae4cddc4da6f07a0d937cf3dc2d 100644
--- a/docs/index.yaml
+++ b/docs/index.yaml
@@ -1,6 +1,76 @@
 apiVersion: v1
 entries:
   theodolite:
+  - apiVersion: v2
+    appVersion: 0.7.0
+    created: "2022-05-11T13:49:02.491041789+02:00"
+    dependencies:
+    - condition: grafana.enabled
+      name: grafana
+      repository: https://grafana.github.io/helm-charts
+      version: 6.17.5
+    - condition: kube-prometheus-stack.enabled
+      name: kube-prometheus-stack
+      repository: https://prometheus-community.github.io/helm-charts
+      version: 20.0.1
+    - condition: cp-helm-charts.enabled
+      name: cp-helm-charts
+      repository: https://soerenhenning.github.io/cp-helm-charts
+      version: 0.6.0
+    - condition: strimzi.enabled
+      name: strimzi-kafka-operator
+      repository: https://strimzi.io/charts/
+      version: 0.28.0
+    description: Theodolite is a framework for benchmarking the horizontal and vertical
+      scalability of cloud-native applications.
+    digest: af10134baa30bb07423f78240fe1c609381e1c616585883cf5d3aded2d86a2b1
+    home: https://www.theodolite.rocks
+    maintainers:
+    - email: soeren.henning@email.uni-kiel.de
+      name: Sören Henning
+      url: https://www.se.informatik.uni-kiel.de/en/team/soeren-henning-m-sc
+    name: theodolite
+    sources:
+    - https://github.com/cau-se/theodolite
+    type: application
+    urls:
+    - https://github.com/cau-se/theodolite/releases/download/v0.7.0/theodolite-0.7.0.tgz
+    version: 0.7.0
+  - apiVersion: v2
+    appVersion: 0.6.4
+    created: "2022-02-16T16:09:11.967649304+01:00"
+    dependencies:
+    - condition: grafana.enabled
+      name: grafana
+      repository: https://grafana.github.io/helm-charts
+      version: 6.17.5
+    - condition: kube-prometheus-stack.enabled
+      name: kube-prometheus-stack
+      repository: https://prometheus-community.github.io/helm-charts
+      version: 20.0.1
+    - condition: cp-helm-charts.enabled
+      name: cp-helm-charts
+      repository: https://soerenhenning.github.io/cp-helm-charts
+      version: 0.6.0
+    - condition: kafka-lag-exporter.enabled
+      name: kafka-lag-exporter
+      repository: https://seanglover.com/kafka-lag-exporter/repo
+      version: 0.6.7
+    description: Theodolite is a framework for benchmarking the horizontal and vertical
+      scalability of cloud-native applications.
+    digest: 10156d9917233ffa297aab093532038667d25b2babb2b2058a0a32e1dccb0cca
+    home: https://www.theodolite.rocks
+    maintainers:
+    - email: soeren.henning@email.uni-kiel.de
+      name: Sören Henning
+      url: https://www.se.informatik.uni-kiel.de/en/team/soeren-henning-m-sc
+    name: theodolite
+    sources:
+    - https://github.com/cau-se/theodolite
+    type: application
+    urls:
+    - https://github.com/cau-se/theodolite/releases/download/v0.6.4/theodolite-0.6.4.tgz
+    version: 0.6.4
   - apiVersion: v2
     appVersion: 0.6.3
     created: "2022-01-24T13:40:40.07330713+01:00"
@@ -141,6 +211,41 @@ entries:
     urls:
     - https://github.com/cau-se/theodolite/releases/download/v0.6.0/theodolite-0.6.0.tgz
     version: 0.6.0
+  - apiVersion: v2
+    appVersion: 0.5.2
+    created: "2022-02-16T15:43:43.534374597+01:00"
+    dependencies:
+    - condition: grafana.enabled
+      name: grafana
+      repository: https://grafana.github.io/helm-charts
+      version: 6.17.5
+    - condition: kube-prometheus-stack.enabled
+      name: kube-prometheus-stack
+      repository: https://prometheus-community.github.io/helm-charts
+      version: 12.0.0
+    - condition: cp-helm-charts.enabled
+      name: cp-helm-charts
+      repository: https://soerenhenning.github.io/cp-helm-charts
+      version: 0.6.0
+    - condition: kafka-lag-exporter.enabled
+      name: kafka-lag-exporter
+      repository: https://seanglover.com/kafka-lag-exporter/repo
+      version: 0.6.6
+    description: Theodolite is a framework for benchmarking the scalability stream
+      processing engines.
+    digest: 72df752883d2161fdfc0e96bb90fe11f9c0ed4f71013e588ec170f2cbb178e9c
+    home: https://cau-se.github.io/theodolite
+    maintainers:
+    - email: soeren.henning@email.uni-kiel.de
+      name: Sören Henning
+      url: https://www.se.informatik.uni-kiel.de/en/team/soeren-henning-m-sc
+    name: theodolite
+    sources:
+    - https://github.com/cau-se/theodolite
+    type: application
+    urls:
+    - https://github.com/cau-se/theodolite/releases/download/v0.5.2/theodolite-0.5.2.tgz
+    version: 0.5.2
   - apiVersion: v2
     appVersion: 0.5.1
     created: "2021-11-12T16:15:01.629937292+01:00"
@@ -246,4 +351,4 @@ entries:
     urls:
     - https://github.com/cau-se/theodolite/releases/download/v0.4.0/theodolite-0.4.0.tgz
     version: 0.4.0
-generated: "2022-01-24T13:40:40.036786105+01:00"
+generated: "2022-05-11T13:49:02.423487026+02:00"
diff --git a/docs/installation.md b/docs/installation.md
index a97e5ea499657cdc3c40f3c03a13c974b5a39bab..d1c7ac3d1dd68d244c556e1ade53b50330aec6ed 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -58,13 +58,13 @@ In cases, where you need to install multiple Theodolite instances, it's best to
 
 ### Installation with a release name other than `theodolite`
 
-When using another release name than `theodolite`, make sure to adjust the Kafka Lag Exporter configuration of you `values.yaml` accordingly:
+When using another release name than `theodolite`, make sure to adjust the Confluent Schema Registry configuration of you `values.yaml` accordingly:
 
 ```yaml
-kafka-lag-exporter:
-  clusters:
-  - name: "<your-release-name>-cp-kafka"
-    bootstrapBrokers: "<your-release-name>-cp-kafka:9092"
+cp-helm-charts:
+  cp-schema-registry:
+    kafka:
+      bootstrapServers: <your-release-name>-kafka-kafka-bootstrap:9092
 ```
 
 This seems unfortunately to be necessary as Helm does not let us inject values into dependency charts.
diff --git a/docs/running-benchmarks.md b/docs/running-benchmarks.md
index 0a76316c0515233f9445b363f941d60ab7aa0e06..5051cb5b685deb17212c1489c585e75262bf9da5 100644
--- a/docs/running-benchmarks.md
+++ b/docs/running-benchmarks.md
@@ -130,7 +130,7 @@ If [persisting results](installation#persisting-results) is enabled in Theodolit
 For installations without persistence, but also as an alternative for installations with persistence, we provide a second option to access results: Theodolite comes with a *results access sidecar*. It allows to copy all benchmark results from the Theodolite pod to your current working directory on your host machine with the following command:
 
 ```sh
-kubectl cp $(kubectl get pod -l app=theodolite -o jsonpath="{.items[0].metadata.name}"):/results . -c results-access
+kubectl cp $(kubectl get pod -l app=theodolite -o jsonpath="{.items[0].metadata.name}"):results . -c results-access
 ```
 
 ## Analyzing Benchmark Results
diff --git a/docs/theodolite-benchmarks/load-generator.md b/docs/theodolite-benchmarks/load-generator.md
index 6d42ea06d9cb008a9aeddcc8145a2868c8d916b1..a41c97d52f62f399c9289a15a64991d0fed228ce 100644
--- a/docs/theodolite-benchmarks/load-generator.md
+++ b/docs/theodolite-benchmarks/load-generator.md
@@ -17,7 +17,7 @@ For each benchmark, we provide a [load generator as OCI container image](https:/
 You can simply run a load generator container, for example, for benchmark UC1 with:
 
 ```sh
-docker run ghcr.io/cau-se/theodolite-uc1-workload-generator
+docker run -it ghcr.io/cau-se/theodolite-uc1-workload-generator
 ```
 
 ### Message format
@@ -47,7 +47,7 @@ The prebuilt container images can be configured with the following environment v
 | `PORT` | Port used for for coordination among load generator instances. | 5701 |
 | `PORT_AUTO_INCREMENT` | If set to true and the specified PORT is already used, use the next higher one. Useful if multiple instances should run on the same host, without configuring each instance individually. | true |
 | `CLUSTER_NAME_PREFIX` | Only required if unrelated load generators form a cluster. | theodolite-load-generation |
-| `TARGET` | The target system the load generator send messages to. Valid values are: `kafka`, `http`. | `kafka` |
+| `TARGET` | The target system the load generator send messages to. Valid values are: `kafka`, `http` and `pubsub`. | `kafka` |
 | `KAFKA_BOOTSTRAP_SERVERS` | A list of host/port pairs to use for establishing the initial connection to the Kafka cluster. See [Kafka producer config: `bootstrap.servers`](https://kafka.apache.org/documentation/#producerconfigs_bootstrap.servers) for more information. Only used if Kafka is set as `TARGET`. | `localhost:9092` |
 | `KAFKA_INPUT_TOPIC` | Name of the Kafka topic, which should receive the generated messages. Only used if Kafka is set as `TARGET`. | input |
 | `SCHEMA_REGISTRY_URL` | URL of the [Confluent Schema Registry](https://docs.confluent.io/platform/current/schema-registry). | `http://localhost:8081` |
@@ -55,19 +55,25 @@ The prebuilt container images can be configured with the following environment v
 | `KAFKA_LINGER_MS` | Value for the Kafka producer configuration: [`linger.ms`](https://kafka.apache.org/documentation/#producerconfigs_linger.ms). Only used if Kafka is set as `TARGET`. | see Kafka producer config: [`linger.ms`](https://kafka.apache.org/documentation/#producerconfigs_linger.ms) |
 | `KAFKA_BUFFER_MEMORY` | Value for the Kafka producer configuration: [`buffer.memory`](https://kafka.apache.org/documentation/#producerconfigs_buffer.memory) Only used if Kafka is set as `TARGET`. | see Kafka producer config: [`buffer.memory`](https://kafka.apache.org/documentation/#producerconfigs_buffer.memory) |
 | `HTTP_URL` | The URL the load generator should post messages to. Only used if HTTP is set as `TARGET`. | |
+| `HTTP_ASYNC` | Whether the load generator should send HTTP messages asynchronously. Only used if HTTP is set as `TARGET`. | `false` |
+| `HTTP_TIMEOUT_MS` | Timeout in milliseconds for sending HTTP messages. Only used if HTTP is set as `TARGET`. | 1000 |
+| `PUBSUB_INPUT_TOPIC` | The Google Cloud Pub/Sub topic to write messages to. Only used if Pub/Sub is set as `TARGET`. | input |
+| `PUBSUB_PROJECT` | The Google Cloud this Pub/Sub topic is associated with. Only used if Pub/Sub is set as `TARGET`. | |
+| `PUBSUB_EMULATOR_HOST` | A Pub/Sub emulator host. Only used if Pub/Sub is set as `TARGET`. | |
 | `NUM_SENSORS` | The amount of simulated sensors. | 10 |
 | `PERIOD_MS` | The time in milliseconds between generating two messages for the same sensor. With our Theodolite benchmarks, we apply an [open workload model](https://www.usenix.org/legacy/event/nsdi06/tech/full_papers/schroeder/schroeder.pdf) in which new messages are generated at a fixed rate, without considering the think time of the target server nor the time required for generating a message. | 1000 |
 | `VALUE` | The constant `valueInW` of an `ActivePowerRecord`. | 10 |
 | `THREADS` | Number of worker threads used to generate the load. | 4 |
+| `DISABLE_DNS_CACHING` | Set to `true` to disable DNS caching by the underlying JVM. You might want to do so when generating load via HTTP that should be sent to different target instances. | `false` |
 
-Please note that there are some additional configuration options for benchmark [UC4's load generator](https://github.com/cau-se/theodolite/blob/master/theodolite-benchmarks/uc4-load-generator/src/main/java/theodolite/uc4/workloadgenerator/LoadGenerator.java).
+Please note that there are some additional configuration options for benchmark [UC4's load generator](hhttps://github.com/cau-se/theodolite/blob/master/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/LoadGenerator.java).
 
 ## Creating a custom load generator
 
-To create a custom load generator, you need to import the [load-generator-commons](https://github.com/cau-se/theodolite/tree/master/theodolite-benchmarks/load-generator-commons) project. You can then create an instance of the `LoadGenerator` object and call its `run` method:
+To create a custom load generator, you need to import the [load-generator-commons](https://github.com/cau-se/theodolite/tree/master/theodolite-benchmarks/load-generator-commons) project. You can then create an instance of the `LoadGenerator` populated with a default configuration, adjust it as desired, and start it by calling its `run` method:
 
 ```java
-LoadGenerator loadGenerator = new LoadGenerator()
+LoadGenerator loadGenerator = new LoadGenerator.fromDefaults()
     .setClusterConfig(clusterConfig)
     .setLoadDefinition(new WorkloadDefinition(
         new KeySpace(key_prefix, numSensors),
@@ -79,9 +85,8 @@ LoadGenerator loadGenerator = new LoadGenerator()
 loadGenerator.run();
 ```
 
-Alternatively, you can also start with a load generator populated with a default configuration or created from environment variables and then adjust the `LoadGenerator` as desired:
+Alternatively, you can also start with a `LoadGenerator` created from environment variables and, optionally, adjust it as desired:
 
 ```java
-LoadGenerator loadGeneratorFromDefaults = LoadGenerator.fromDefaults()
-LoadGenerator loadGeneratorFromEnv = LoadGenerator.fromEnvironment();
+LoadGenerator loadGenerator = LoadGenerator.fromEnvironment();
 ```
diff --git a/execution/infrastructure/zookeeper-client.yaml b/execution/infrastructure/zookeeper-client.yaml
index 9d6d00275c46a888ed4e8ff08533ca245c4a684c..85739bba751be62773f511aa95030e6d71a4a869 100644
--- a/execution/infrastructure/zookeeper-client.yaml
+++ b/execution/infrastructure/zookeeper-client.yaml
@@ -2,10 +2,12 @@ apiVersion: v1
 kind: Pod
 metadata:
   name: zookeeper-client
+  labels:
+    app: zookeeper-client
 spec:
   containers:
   - name: zookeeper-client
-    image: confluentinc/cp-zookeeper:5.4.0
+    image: zookeeper:3.7.0
     command:
       - sh
       - -c
diff --git a/helm/Chart.yaml b/helm/Chart.yaml
index 27451ad55ce75592db9dc7550b1f81dced3951bc..5d707a70599b8a26ce828c94223ac20903f71848 100644
--- a/helm/Chart.yaml
+++ b/helm/Chart.yaml
@@ -24,11 +24,12 @@ dependencies:
     version: 0.6.0
     repository: https://soerenhenning.github.io/cp-helm-charts
     condition: cp-helm-charts.enabled
-  - name: kafka-lag-exporter
-    version: 0.6.7
-    repository: https://lightbend.github.io/kafka-lag-exporter/repo/
-    condition: kafka-lag-exporter.enabled
+  - name: strimzi-kafka-operator
+    version: 0.28.0
+    repository: https://strimzi.io/charts/
+    condition: strimzi.enabled
 
-version: 0.7.0-SNAPSHOT
 
-appVersion: 0.7.0-SNAPSHOT
+version: 0.8.0-SNAPSHOT
+
+appVersion: 0.8.0-SNAPSHOT
diff --git a/helm/preconfigs/minimal.yaml b/helm/preconfigs/minimal.yaml
index 80a83f06cc9838e01f812e730932b9b79d947161..3f2dba0b55b729654125377996381718d7c15eb4 100644
--- a/helm/preconfigs/minimal.yaml
+++ b/helm/preconfigs/minimal.yaml
@@ -1,15 +1,15 @@
-cp-helm-charts:
-  cp-zookeeper:
-    servers: 1
-
-  cp-kafka:
-    brokers: 1
-    configurationOverrides:
-      offsets.topic.replication.factor: "1"
-
 operator:
   sloChecker:
     droppedRecordsKStreams:
       enabled: false
   resultsVolume:
     enabled: false
+
+strimzi:
+  kafka:
+    replicas: 1
+    config: 
+      "offsets.topic.replication.factor": "1"
+  zookeeper:
+    replicas: 1
+  
\ No newline at end of file
diff --git a/helm/templates/grafana/dashboard-config-map.yaml b/helm/templates/grafana/dashboard-config-map.yaml
index 0df01b20efa0fb1100fe4b7289b00b3058eb032f..459021213c1d4c746819ddabac790800b9a6ed09 100644
--- a/helm/templates/grafana/dashboard-config-map.yaml
+++ b/helm/templates/grafana/dashboard-config-map.yaml
@@ -71,10 +71,10 @@ data:
         "steppedLine": false,
         "targets": [
           {
-            "expr": "sum(cp_kafka_server_brokertopicmetrics_messagesinpersec_topic_input)",
+            "expr": "sum by (topic) (rate(kafka_server_brokertopicmetrics_messagesin_total{topic='input'}[30s]))",
             "format": "time_series",
             "intervalFactor": 1,
-            "legendFormat": "{{Messages In Per Second}}",
+            "legendFormat": "{{topic}}",
             "refId": "D"
           }
         ],
@@ -162,10 +162,10 @@ data:
         "steppedLine": false,
         "targets": [
           {
-            "expr": "sum(cp_kafka_server_brokertopicmetrics_messagesinpersec_topic_output)",
+            "expr": "sum by (topic) (rate(kafka_server_brokertopicmetrics_messagesin_total{topic='output'}[30s]))",
             "format": "time_series",
             "intervalFactor": 1,
-            "legendFormat": "{{Messages Out Per Second}}",
+            "legendFormat": "{{topic}}",
             "refId": "D"
           }
         ],
@@ -253,7 +253,7 @@ data:
         "steppedLine": false,
         "targets": [
           {
-            "expr": "sum by(group, topic) (kafka_consumergroup_group_lag >= 0)",
+            "expr": "sum by(consumergroup, topic) (kafka_consumergroup_lag >= 0)",
             "format": "time_series",
             "intervalFactor": 1,
             "legendFormat": "{{topic}}",
@@ -344,10 +344,10 @@ data:
         "steppedLine": false,
         "targets": [
           {
-            "expr": "count(count (kafka_consumer_consumer_fetch_manager_metrics_records_lag) by(pod))",
+            "expr": "sum by(consumergroup) (kafka_consumergroup_members >= 0)",
             "format": "time_series",
             "intervalFactor": 1,
-            "legendFormat": "instances",
+            "legendFormat": "{{consumergroup}}",
             "refId": "D"
           }
         ],
@@ -436,7 +436,7 @@ data:
         "steppedLine": false,
         "targets": [
           {
-            "expr": "sum by(group,topic) (kafka_consumergroup_group_offset >= 0)",
+            "expr": "sum by(consumergroup,topic) (kafka_consumergroup_current_offset{topic='input'} >= 0)",
             "format": "time_series",
             "intervalFactor": 1,
             "legendFormat": "{{topic}}",
@@ -527,7 +527,7 @@ data:
         "steppedLine": false,
         "targets": [
           {
-            "expr": "count by(group,topic) (kafka_consumergroup_group_offset >= 0)",
+            "expr": "kafka_topic_partitions",
             "format": "time_series",
             "intervalFactor": 1,
             "legendFormat": "{{topic}}",
@@ -618,7 +618,7 @@ data:
         "steppedLine": false,
         "targets": [
           {
-            "expr": "sum by(group,topic) (kafka_partition_latest_offset)",
+            "expr": "sum by(topic) (kafka_topic_partition_current_offset)",
             "format": "time_series",
             "intervalFactor": 1,
             "legendFormat": "{{topic}}",
diff --git a/helm/templates/kafka/kafka-client.yaml b/helm/templates/kafka/kafka-client.yaml
index 02e16d33dfc9595dd16c41fa6bfe1404fd7889ab..1edf1b96c7326d6a3cfdb1a45640ec9d8d720fba 100644
--- a/helm/templates/kafka/kafka-client.yaml
+++ b/helm/templates/kafka/kafka-client.yaml
@@ -2,7 +2,6 @@
 apiVersion: v1
 kind: Pod
 metadata:
-  # name: {{ template "theodolite.fullname" . }}-kafka-client
   name: {{ template "theodolite.fullname" . }}-kafka-client
 spec:
   containers:
@@ -12,6 +11,9 @@ spec:
       - sh
       - -c
       - "exec tail -f /dev/null"
+    env:
+      - name: BOOTSTRAP_SERVER
+        value: {{ template "theodolite.fullname" . }}-kafka-kafka-bootstrap:9092
   {{- with .Values.kafkaClient.nodeSelector }}
   nodeSelector:
     {{- toYaml . | nindent 8 }}
diff --git a/helm/templates/kafka/kafka-cluster.yaml b/helm/templates/kafka/kafka-cluster.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f1a58077a78865c624706531b58c3150feeb83ae
--- /dev/null
+++ b/helm/templates/kafka/kafka-cluster.yaml
@@ -0,0 +1,73 @@
+{{- if .Values.strimzi.enabled -}}
+apiVersion: kafka.strimzi.io/v1beta2
+kind: Kafka
+metadata:
+  name: {{ template "theodolite.fullname" . }}-kafka
+spec:
+  kafka:
+    jmxOptions: {}
+    {{- with .Values.strimzi.kafka.listeners }}
+    listeners:
+      {{- toYaml . | nindent 6 }}
+    {{- end }}
+    {{- with .Values.strimzi.kafka.replicas }}
+    replicas:
+      {{- toYaml . | nindent 6 }}
+    {{- end }}
+    {{- with .Values.strimzi.kafka.config }}
+    config:
+      {{- toYaml . | nindent 6 }}
+    {{- end }}
+    {{- with .Values.strimzi.kafka.jvmOptions }}
+    jvmOptions:
+      {{- toYaml . | nindent 6 }}
+    {{- end }}
+    storage:
+      type: ephemeral
+    metricsConfig:
+      type: jmxPrometheusExporter
+      valueFrom:
+        configMapKeyRef:
+          name: {{ template "theodolite.fullname" . }}-kafka-metrics
+          key: kafka-metrics-config.yml
+    {{- with .Values.strimzi.kafka.nodeSelectorTerms}}
+    template:
+      pod:
+        affinity:
+          nodeAffinity:
+            requiredDuringSchedulingIgnoredDuringExecution:
+              nodeSelectorTerms:
+                {{- toYaml . | nindent 16 }}
+    {{- end}}
+    {{- with .Values.strimzi.kafka.resources}}
+    resources:
+      {{- toYaml . | nindent 6 }}
+    {{- end}}
+
+
+  zookeeper:
+    {{- with .Values.strimzi.zookeeper.replicas }}
+    replicas:
+      {{- toYaml . | nindent 6 }}
+    {{- end }}
+    storage:
+      type: ephemeral
+    {{- with .Values.strimzi.zookeeper.nodeSelectorTerms}}
+    template:
+      pod:
+        affinity:
+          nodeAffinity:
+            requiredDuringSchedulingIgnoredDuringExecution:
+              nodeSelectorTerms:
+                {{- toYaml . | nindent 16 }}
+    {{- end}}
+
+  kafkaExporter: {}
+
+  {{- if .Values.strimzi.topicOperator.enabled }}
+  entityOperator:
+    topicOperator: {}
+  {{- end }}
+
+
+{{- end }}
\ No newline at end of file
diff --git a/helm/templates/kafka/kafka-exporter-podmonitor.yaml b/helm/templates/kafka/kafka-exporter-podmonitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..41395dfd6a9ea9f74598ff89c4d9e2e7f8757ff0
--- /dev/null
+++ b/helm/templates/kafka/kafka-exporter-podmonitor.yaml
@@ -0,0 +1,16 @@
+{{- if .Values.strimzi.enabled -}}
+apiVersion: monitoring.coreos.com/v1
+kind: PodMonitor
+metadata:
+  name: {{ template "theodolite.fullname" . }}-kafka-exporter-podmonitor
+  labels:
+    app: theodolite
+spec:
+  selector:
+    selector:
+    matchLabels:
+      strimzi.io/name: {{ template "theodolite.fullname" . }}-kafka-kafka-exporter
+  podMetricsEndpoints:
+  - path: /metrics
+    port: tcp-prometheus
+{{- end }}
\ No newline at end of file
diff --git a/helm/templates/kafka/kafka-metrics-configmap.yaml b/helm/templates/kafka/kafka-metrics-configmap.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ad75bfa6ab9ec89a229125d167b897cb58744c42
--- /dev/null
+++ b/helm/templates/kafka/kafka-metrics-configmap.yaml
@@ -0,0 +1,133 @@
+{{- if .Values.strimzi.enabled -}}
+kind: ConfigMap
+apiVersion: v1
+metadata:
+  name: {{ template "theodolite.fullname" . }}-kafka-metrics
+  labels:
+    app: strimzi
+data:
+  kafka-metrics-config.yml: |
+    # See https://github.com/prometheus/jmx_exporter for more info about JMX Prometheus Exporter metrics
+    lowercaseOutputName: true
+    rules:
+    # Special cases and very specific rules
+    - pattern: kafka.server<type=(.+), name=(.+), clientId=(.+), topic=(.+), partition=(.*)><>Value
+      name: kafka_server_$1_$2
+      type: GAUGE
+      labels:
+       clientId: "$3"
+       topic: "$4"
+       partition: "$5"
+    - pattern: kafka.server<type=(.+), name=(.+), clientId=(.+), brokerHost=(.+), brokerPort=(.+)><>Value
+      name: kafka_server_$1_$2
+      type: GAUGE
+      labels:
+       clientId: "$3"
+       broker: "$4:$5"
+    - pattern: kafka.server<type=(.+), cipher=(.+), protocol=(.+), listener=(.+), networkProcessor=(.+)><>connections
+      name: kafka_server_$1_connections_tls_info
+      type: GAUGE
+      labels:
+        cipher: "$2"
+        protocol: "$3"
+        listener: "$4"
+        networkProcessor: "$5"
+    - pattern: kafka.server<type=(.+), clientSoftwareName=(.+), clientSoftwareVersion=(.+), listener=(.+), networkProcessor=(.+)><>connections
+      name: kafka_server_$1_connections_software
+      type: GAUGE
+      labels:
+        clientSoftwareName: "$2"
+        clientSoftwareVersion: "$3"
+        listener: "$4"
+        networkProcessor: "$5"
+    - pattern: "kafka.server<type=(.+), listener=(.+), networkProcessor=(.+)><>(.+):"
+      name: kafka_server_$1_$4
+      type: GAUGE
+      labels:
+       listener: "$2"
+       networkProcessor: "$3"
+    - pattern: kafka.server<type=(.+), listener=(.+), networkProcessor=(.+)><>(.+)
+      name: kafka_server_$1_$4
+      type: GAUGE
+      labels:
+       listener: "$2"
+       networkProcessor: "$3"
+    # Some percent metrics use MeanRate attribute
+    # Ex) kafka.server<type=(KafkaRequestHandlerPool), name=(RequestHandlerAvgIdlePercent)><>MeanRate
+    - pattern: kafka.(\w+)<type=(.+), name=(.+)Percent\w*><>MeanRate
+      name: kafka_$1_$2_$3_percent
+      type: GAUGE
+    # Generic gauges for percents
+    - pattern: kafka.(\w+)<type=(.+), name=(.+)Percent\w*><>Value
+      name: kafka_$1_$2_$3_percent
+      type: GAUGE
+    - pattern: kafka.(\w+)<type=(.+), name=(.+)Percent\w*, (.+)=(.+)><>Value
+      name: kafka_$1_$2_$3_percent
+      type: GAUGE
+      labels:
+        "$4": "$5"
+    # Generic per-second counters with 0-2 key/value pairs
+    - pattern: kafka.(\w+)<type=(.+), name=(.+)PerSec\w*, (.+)=(.+), (.+)=(.+)><>Count
+      name: kafka_$1_$2_$3_total
+      type: COUNTER
+      labels:
+        "$4": "$5"
+        "$6": "$7"
+    - pattern: kafka.(\w+)<type=(.+), name=(.+)PerSec\w*, (.+)=(.+)><>Count
+      name: kafka_$1_$2_$3_total
+      type: COUNTER
+      labels:
+        "$4": "$5"
+    - pattern: kafka.(\w+)<type=(.+), name=(.+)PerSec\w*><>Count
+      name: kafka_$1_$2_$3_total
+      type: COUNTER
+    # Generic gauges with 0-2 key/value pairs
+    - pattern: kafka.(\w+)<type=(.+), name=(.+), (.+)=(.+), (.+)=(.+)><>Value
+      name: kafka_$1_$2_$3
+      type: GAUGE
+      labels:
+        "$4": "$5"
+        "$6": "$7"
+    - pattern: kafka.(\w+)<type=(.+), name=(.+), (.+)=(.+)><>Value
+      name: kafka_$1_$2_$3
+      type: GAUGE
+      labels:
+        "$4": "$5"
+    - pattern: kafka.(\w+)<type=(.+), name=(.+)><>Value
+      name: kafka_$1_$2_$3
+      type: GAUGE
+    # Emulate Prometheus 'Summary' metrics for the exported 'Histogram's.
+    # Note that these are missing the '_sum' metric!
+    - pattern: kafka.(\w+)<type=(.+), name=(.+), (.+)=(.+), (.+)=(.+)><>Count
+      name: kafka_$1_$2_$3_count
+      type: COUNTER
+      labels:
+        "$4": "$5"
+        "$6": "$7"
+    - pattern: kafka.(\w+)<type=(.+), name=(.+), (.+)=(.*), (.+)=(.+)><>(\d+)thPercentile
+      name: kafka_$1_$2_$3
+      type: GAUGE
+      labels:
+        "$4": "$5"
+        "$6": "$7"
+        quantile: "0.$8"
+    - pattern: kafka.(\w+)<type=(.+), name=(.+), (.+)=(.+)><>Count
+      name: kafka_$1_$2_$3_count
+      type: COUNTER
+      labels:
+        "$4": "$5"
+    - pattern: kafka.(\w+)<type=(.+), name=(.+), (.+)=(.*)><>(\d+)thPercentile
+      name: kafka_$1_$2_$3
+      type: GAUGE
+      labels:
+        "$4": "$5"
+        quantile: "0.$6"
+    - pattern: kafka.(\w+)<type=(.+), name=(.+)><>Count
+      name: kafka_$1_$2_$3_count
+      type: COUNTER
+    - pattern: kafka.(\w+)<type=(.+), name=(.+)><>(\d+)thPercentile
+      name: kafka_$1_$2_$3
+      type: GAUGE
+      labels:
+        quantile: "0.$4"
+{{- end }}
\ No newline at end of file
diff --git a/helm/templates/kafka/kafka-podmonitor.yaml b/helm/templates/kafka/kafka-podmonitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..522f23f305b53615251d80e8cb13eac50e5530ad
--- /dev/null
+++ b/helm/templates/kafka/kafka-podmonitor.yaml
@@ -0,0 +1,16 @@
+{{- if .Values.strimzi.enabled -}}
+apiVersion: monitoring.coreos.com/v1
+kind: PodMonitor
+metadata:
+  name: {{ template "theodolite.fullname" . }}-kafka-resources-metrics
+  labels:
+    app: theodolite
+spec:
+  selector:
+    selector:
+    matchLabels:
+      strimzi.io/name: {{ template "theodolite.fullname" . }}-kafka-kafka
+  podMetricsEndpoints:
+  - path: /metrics
+    port: tcp-prometheus
+{{- end }}
\ No newline at end of file
diff --git a/helm/templates/kafka/zookeeper-client.yaml b/helm/templates/kafka/zookeeper-client.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..2154ec116b71bbb33808d3c32d42170a8d9589da
--- /dev/null
+++ b/helm/templates/kafka/zookeeper-client.yaml
@@ -0,0 +1,23 @@
+{{- if .Values.strimzi.zookeeper.zooEntrance.zookeeperClient.enabled -}}
+apiVersion: v1
+kind: Pod
+metadata:
+  name: {{ template "theodolite.fullname" . }}-kafka-zookeeper-client
+  labels:
+    app: zookeeper-client
+spec:
+  containers:
+  - name: zookeeper-client
+    image: zookeeper:3.7.0
+    command:
+      - sh
+      - -c
+      - "exec tail -f /dev/null"
+    env:
+    - name: ZOOKEEPER_SERVER
+      value: {{ template "theodolite.fullname" . }}-kafka-zoo-entrance:2181
+  {{- with .Values.strimzi.zookeeper.zooEntrance.zookeeperClient.nodeSelector }}
+  nodeSelector:
+    {{- toYaml . | nindent 8 }}
+  {{- end }}
+{{- end }}
\ No newline at end of file
diff --git a/helm/templates/kafka/zookeeper-entrance-deployment.yaml b/helm/templates/kafka/zookeeper-entrance-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a0c2841760aa641b1f1105863465a08069d164bd
--- /dev/null
+++ b/helm/templates/kafka/zookeeper-entrance-deployment.yaml
@@ -0,0 +1,71 @@
+{{- if .Values.strimzi.zookeeper.zooEntrance.enabled -}}
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ template "theodolite.fullname" . }}-kafka-zoo-entrance
+  labels:
+    app: zoo-entrance
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: zoo-entrance
+  strategy:
+    type: Recreate
+  template:
+    metadata:
+      labels:
+        app: zoo-entrance
+    spec:
+      containers:
+        - name: zoo-entrance
+          image: 'ghcr.io/scholzj/zoo-entrance:latest'
+          command:
+            - /opt/stunnel/stunnel_run.sh
+          ports:
+            - containerPort: 2181
+              name: zoo
+              protocol: TCP
+          env:
+            - name: LOG_LEVEL
+              value: notice
+            - name: STRIMZI_ZOOKEEPER_CONNECT
+              value: {{ template "theodolite.fullname" . }}-kafka-zookeeper-client:2181
+          imagePullPolicy: Always
+          livenessProbe:
+            exec:
+              command:
+                - /opt/stunnel/stunnel_healthcheck.sh
+                - '2181'
+            failureThreshold: 3
+            initialDelaySeconds: 15
+            periodSeconds: 10
+            successThreshold: 1
+            timeoutSeconds: 5
+          readinessProbe:
+            exec:
+              command:
+                - /opt/stunnel/stunnel_healthcheck.sh
+                - '2181'
+            failureThreshold: 3
+            initialDelaySeconds: 15
+            periodSeconds: 10
+            successThreshold: 1
+            timeoutSeconds: 5
+          volumeMounts:
+            - mountPath: /etc/cluster-operator-certs/
+              name: cluster-operator-certs
+            - mountPath: /etc/cluster-ca-certs/
+              name: cluster-ca-certs
+      restartPolicy: Always
+      terminationGracePeriodSeconds: 30
+      volumes:
+        - name: cluster-operator-certs
+          secret:
+            defaultMode: 288
+            secretName: {{ template "theodolite.fullname" . }}-kafka-cluster-operator-certs
+        - name: cluster-ca-certs
+          secret:
+            defaultMode: 288
+            secretName: {{ template "theodolite.fullname" . }}-kafka-cluster-ca-cert
+{{- end }}
diff --git a/helm/templates/kafka/zookeeper-entrance-network.yaml b/helm/templates/kafka/zookeeper-entrance-network.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..604095c1ab3f5e207666383e23dfb8f006b196ae
--- /dev/null
+++ b/helm/templates/kafka/zookeeper-entrance-network.yaml
@@ -0,0 +1,22 @@
+{{- if .Values.strimzi.zookeeper.zooEntrance.enabled -}}
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+metadata:
+  labels:
+    app: zoo-entrance
+  name: {{ template "theodolite.fullname" . }}-kafka-zoo-entrance
+spec:
+  ingress:
+  - from:
+    - podSelector:
+        matchLabels:
+          app: zoo-entrance
+    ports:
+    - port: 2181
+      protocol: TCP
+  podSelector:
+    matchLabels:
+      strimzi.io/name: {{ template "theodolite.fullname" . }}-kafka-zookeeper
+  policyTypes:
+  - Ingress
+{{- end }}
diff --git a/helm/templates/kafka/zookeeper-entrance-service.yaml b/helm/templates/kafka/zookeeper-entrance-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..bbb466c3d9ad4e7ff9cb012aaaa95ad9a5380a6e
--- /dev/null
+++ b/helm/templates/kafka/zookeeper-entrance-service.yaml
@@ -0,0 +1,17 @@
+{{- if .Values.strimzi.zookeeper.zooEntrance.enabled -}}
+apiVersion: v1
+kind: Service
+metadata:
+  labels:
+    app: zoo-entrance
+  name: {{ template "theodolite.fullname" . }}-kafka-zoo-entrance
+spec:
+  ports:
+    - name: zoo
+      port: 2181
+      protocol: TCP
+      targetPort: 2181
+  selector:
+    app: zoo-entrance
+  type: ClusterIP
+{{- end }}
diff --git a/helm/templates/prometheus/operator-role-binding.yaml b/helm/templates/prometheus/operator-role-binding.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0fadc048940ca5254e7ce2867a657361f32ef3b7
--- /dev/null
+++ b/helm/templates/prometheus/operator-role-binding.yaml
@@ -0,0 +1,16 @@
+{{- if not (index .Values "kube-prometheus-stack" "global" "rbac" "create") -}}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: {{ template "theodolite.fullname" . }}-kube-prometheus-operator
+  labels:
+    app: {{ template "theodolite.fullname" . }}-kube-prometheus-operator
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: {{ template "theodolite.fullname" . }}-kube-prometheus-operator
+subjects:
+- kind: ServiceAccount
+  name: {{ template "theodolite.fullname" . }}-kube-prometheus-operator
+  namespace: {{ .Release.Namespace }}
+{{- end }}
diff --git a/helm/templates/prometheus/operator-role.yaml b/helm/templates/prometheus/operator-role.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..16481a2ec6a4387e589079433490ac5d437dc04b
--- /dev/null
+++ b/helm/templates/prometheus/operator-role.yaml
@@ -0,0 +1,79 @@
+{{- if not (index .Values "kube-prometheus-stack" "global" "rbac" "create") -}}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: {{ template "theodolite.fullname" . }}-kube-prometheus-operator
+  labels:
+    app: {{ template "theodolite.name" . }}-kube-prometheus-operator
+rules:
+- apiGroups:
+  - monitoring.coreos.com
+  resources:
+  - alertmanagers
+  - alertmanagers/finalizers
+  - alertmanagerconfigs
+  - prometheuses
+  - prometheuses/finalizers
+  - thanosrulers
+  - thanosrulers/finalizers
+  - servicemonitors
+  - podmonitors
+  - probes
+  - prometheusrules
+  verbs:
+  - '*'
+- apiGroups:
+  - apps
+  resources:
+  - statefulsets
+  verbs:
+  - '*'
+- apiGroups:
+  - ""
+  resources:
+  - configmaps
+  - secrets
+  verbs:
+  - '*'
+- apiGroups:
+  - ""
+  resources:
+  - pods
+  verbs:
+  - list
+  - delete
+- apiGroups:
+  - ""
+  resources:
+  - services
+  - services/finalizers
+  - endpoints
+  verbs:
+  - get
+  - create
+  - update
+  - delete
+- apiGroups:
+  - ""
+  resources:
+  - nodes
+  verbs:
+  - list
+  - watch
+- apiGroups:
+  - ""
+  resources:
+  - namespaces
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+  - networking.k8s.io
+  resources:
+  - ingresses
+  verbs:
+  - get
+  - list
+  - watch
+{{- end }}
diff --git a/helm/templates/prometheus/prometheus.yaml b/helm/templates/prometheus/prometheus.yaml
index 23a015250e19cc14550ce73e8162ba27f65be774..196d68487824d7d8e130c56d11cec2687304d7e6 100644
--- a/helm/templates/prometheus/prometheus.yaml
+++ b/helm/templates/prometheus/prometheus.yaml
@@ -5,11 +5,12 @@ metadata:
   name: {{ template "theodolite.fullname" . }}-prometheus
 spec:
   serviceAccountName: {{ template "theodolite.fullname" . }}-prometheus
+  podMonitorSelector: {}
   serviceMonitorSelector: {}
   resources:
     requests:
       memory: 400Mi
-  #scrapeInterval: 1s
+  scrapeInterval: 15s
   enableAdminAPI: true
   {{- with .Values.prometheus.nodeSelector }}
   nodeSelector:
diff --git a/helm/templates/prometheus/cluster-role-binding.yaml b/helm/templates/prometheus/role-binding.yaml
similarity index 75%
rename from helm/templates/prometheus/cluster-role-binding.yaml
rename to helm/templates/prometheus/role-binding.yaml
index f2f167b94b79ad4db130565777cb8af486762c8c..722f806e0621a5775083f74f064e0c9eae18f1d8 100644
--- a/helm/templates/prometheus/cluster-role-binding.yaml
+++ b/helm/templates/prometheus/role-binding.yaml
@@ -1,14 +1,14 @@
-{{- if .Values.prometheus.clusterRoleBinding.enabled -}}
+{{- if .Values.prometheus.roleBinding.enabled -}}
 apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRoleBinding
+kind: RoleBinding
 metadata:
   name: {{ template "theodolite.fullname" . }}-prometheus
 roleRef:
   apiGroup: rbac.authorization.k8s.io
-  kind: ClusterRole
+  kind: Role
   name: {{ template "theodolite.fullname" . }}-prometheus
 subjects:
 - kind: ServiceAccount
   name: {{ template "theodolite.fullname" . }}-prometheus
   namespace: {{ .Release.Namespace }}
-{{- end}}
\ No newline at end of file
+{{- end}}
diff --git a/helm/templates/prometheus/cluster-role.yaml b/helm/templates/prometheus/role.yaml
similarity index 67%
rename from helm/templates/prometheus/cluster-role.yaml
rename to helm/templates/prometheus/role.yaml
index c2fea2205451e01474d1ab7ef1ca342a9d975dc9..321d2825b5b98d31fc34619e88994058bac74cab 100644
--- a/helm/templates/prometheus/cluster-role.yaml
+++ b/helm/templates/prometheus/role.yaml
@@ -1,12 +1,11 @@
-{{- if .Values.prometheus.clusterRole.enabled -}}
+{{- if .Values.prometheus.role.enabled -}}
 apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRole
+kind: Role
 metadata:
   name: {{ template "theodolite.fullname" . }}-prometheus
 rules:
 - apiGroups: [""]
   resources:
-  - nodes
   - services
   - endpoints
   - pods
@@ -15,6 +14,4 @@ rules:
   resources:
   - configmaps
   verbs: ["get"]
-- nonResourceURLs: ["/metrics"]
-  verbs: ["get"]
-{{- end }}
\ No newline at end of file
+{{- end}}
diff --git a/helm/templates/theodolite/role.yaml b/helm/templates/theodolite/role.yaml
index 43ee0e43d6974cd95548df32d6c4b1df8f3e497e..b8d4d2d005d5a969c2c72cdca145f829d748e419 100644
--- a/helm/templates/theodolite/role.yaml
+++ b/helm/templates/theodolite/role.yaml
@@ -38,12 +38,26 @@ rules:
     - monitoring.coreos.com
     resources:
     - servicemonitors
+    - podmonitors
     verbs:
     - update
     - delete
     - list
     - create
     - get
+  - apiGroups:
+    - kafka.strimzi.io
+    resources:
+    - kafkatopics
+    verbs:
+    - delete
+    - list
+    - get
+    - create
+    - update
+  {{- with .Values.rbac.additionalRules }}
+{{ toYaml . | indent 2 }}
+  {{- end }}
   {{- if .Values.operator.enabled }}
   - apiGroups:
     - theodolite.com
diff --git a/helm/values.yaml b/helm/values.yaml
index ba58b040974886518ab111d668cb0db1140b2eb8..34a32ce60927a751f645b7f8ff4af46793865797 100644
--- a/helm/values.yaml
+++ b/helm/values.yaml
@@ -5,7 +5,7 @@
 kafkaClient:
   enabled: false
   nodeSelector: {}
-  
+
 
 ####
 ## configuration of sub charts
@@ -52,6 +52,9 @@ grafana:
   service:
     nodePort: 31199
     type: NodePort
+  rbac:
+    pspEnabled: false
+    namespaced: true
 
 
 ###
@@ -64,7 +67,7 @@ cp-helm-charts:
   ## Zookeeper
   ## ------------------------------------------------------
   cp-zookeeper:
-    enabled: true
+    enabled: false
     nodeSelector: {}
     servers: 3
     image: confluentinc/cp-zookeeper
@@ -81,7 +84,7 @@ cp-helm-charts:
   ## Kafka
   ## ------------------------------------------------------
   cp-kafka:
-    enabled: true
+    enabled: false
     nodeSelector: {}
     brokers: 3
     image: confluentinc/cp-enterprise-kafka
@@ -137,6 +140,9 @@ cp-helm-charts:
       nodePort: 30099
       annotations: {}
 
+    kafka:
+      bootstrapServers: theodolite-kafka-kafka-bootstrap:9092
+
   cp-kafka-rest:
     enabled: false
 
@@ -149,35 +155,54 @@ cp-helm-charts:
   cp-control-center:
     enabled: false
 
-
-###
-# Kafka Lag Exporter
-###
-kafka-lag-exporter:
-  enabled: true
-  image:
-    pullPolicy: IfNotPresent
-  nodeSelector: {}
-  
-  clusters:
-    - name: "theodolite-cp-kafka"
-      bootstrapBrokers: "theodolite-cp-kafka:9092"
-
   ## The interval between refreshing metrics
   pollIntervalSeconds: 15
 
-  prometheus:
-    serviceMonitor:
+strimzi-kafka-operator:
+  createGlobalResources: true
+
+strimzi:
+  enabled: true
+  kafka:
+    listeners:
+      - name: plain
+        port: 9092
+        type: internal
+        tls: false
+    replicas: 3
+    config:
+      "message.max.bytes": "134217728" # 128 MB
+      "replica.fetch.max.bytes": "134217728" #128 MB
+      "auto.create.topics.enable": false
+      "log.retention.ms": "7200000" # 2h
+      "metrics.sample.window.ms": "5000" #5s
+    jvmOptions:
+      "-Xmx": "512M"
+      "-Xms": "512M"
+    nodeSelectorTerms: []
+    resources: {}
+    
+  zookeeper:
+    replicas: 3
+    zooEntrance:
       enabled: true
-      interval: "5s"
-      additionalLabels:
-        appScope: titan-ccp
+      zookeeperClient:
+        enabled: true
+        nodeSelector: {}
+    nodeSelectorTerms: []
+  
+  topicOperator:
+    enabled: true
 
 
 ###
 # Prometheus Monitoring Stack (Prometheus Operator)
 ###
 kube-prometheus-stack:
+  global:
+    rbac:
+      create: false
+
   commonLabels:
     appScope: titan-ccp
   
@@ -223,7 +248,14 @@ kube-prometheus-stack:
       releaseNamespace: true
       additional: []
     nodeSelector: {}
+    admissionWebhooks:
+      enabled: false
+    tls:
+      enabled: false
+    serviceAccount:
+      create: true
   
+  # We use our own Prometheus
   prometheus:
     enabled: false
 
@@ -235,12 +267,11 @@ prometheus:
   enabled: true
   nodeSelector: {}
   
-  # depends on your cluster security and permission settings, you may need to create the following resources
   serviceAccount:
     enabled: true
-  clusterRole:
+  role:
     enabled: true
-  clusterRoleBinding:
+  roleBinding:
     enabled: true
 
 ###
@@ -291,33 +322,50 @@ operator:
       uc1LoadGenerator: true
       uc1Kstreams: true
       uc1Flink: true
+      uc1BeamFlink: true
+      uc1BeamSamza: true
       uc2LoadGenerator: true
       uc2Kstreams: true
       uc2Flink: true
+      uc2BeamFlink: true
+      uc2BeamSamza: true
       uc3LoadGenerator: true
       uc3Kstreams: true
       uc3Flink: true
+      uc3BeamFlink: true
+      uc3BeamSamza: true
       uc4LoadGenerator: true
       uc4Kstreams: true
       uc4Flink: true
+      uc4BeamFlink: true
+      uc4BeamSamza: true
     benchmarks:
       uc1Kstreams: true
       uc1Flink: true
+      uc1BeamFlink: true
+      uc1BeamSamza: true
       uc2Kstreams: true
       uc2Flink: true
+      uc2BeamFlink: true
+      uc2BeamSamza: true
       uc3Kstreams: true
       uc3Flink: true
+      uc3BeamFlink: true
+      uc3BeamSamza: true
       uc4Kstreams: true
       uc4Flink: true
+      uc4BeamFlink: true
+      uc4BeamSamza: true
 
 serviceAccount:
   create: true
 
 rbac:
   create: true
+  additionalRules: []
 
 randomScheduler:
-  enabled: true
+  enabled: false
   image: ghcr.io/cau-se/theodolite-random-scheduler
   imageTag: latest
   imagePullPolicy: Always
diff --git a/slo-checker/generic/app/main.py b/slo-checker/generic/app/main.py
index f36c8739da00128ad94feb1f2d7871df7e2ff137..e483c26b4f421d00e093ad70ff8d12d0a9bb9e62 100644
--- a/slo-checker/generic/app/main.py
+++ b/slo-checker/generic/app/main.py
@@ -37,7 +37,7 @@ def aggr_query(values: dict, warmup: int, aggr_func):
     df = pd.DataFrame.from_dict(values)
     df.columns = ['timestamp', 'value']
     filtered = df[df['timestamp'] >= (df['timestamp'][0] + warmup)]
-    filtered['value'] = filtered['value'].astype(int)
+    filtered['value'] = filtered['value'].astype(float).astype(int)
     return filtered['value'].aggregate(aggr_func)
 
 def check_result(result, operator: str, threshold):
diff --git a/slo-checker/generic/resources/test-1-rep-success.json b/slo-checker/generic/resources/test-1-rep-success.json
index b70f461cf620d8eee8c4d9d93feb46db7498626f..9a6db686ec632f72f0d1981657826a8443b4c348 100644
--- a/slo-checker/generic/resources/test-1-rep-success.json
+++ b/slo-checker/generic/resources/test-1-rep-success.json
@@ -260,7 +260,7 @@
                     ],
                     [
                         1.634624989695E9,
-                        "1854284"
+                        "3970.0000000000005"
                     ]
                 ]
             }
diff --git a/slo-checker/record-lag/app/main.py b/slo-checker/record-lag/app/main.py
index 621fa0cfc9c27e809fd92752de93f2795fa32c05..bb68580a638a40bc7ae975594b859d10784adc67 100644
--- a/slo-checker/record-lag/app/main.py
+++ b/slo-checker/record-lag/app/main.py
@@ -24,7 +24,7 @@ elif os.getenv('LOG_LEVEL') == 'DEBUG':
 def calculate_slope_trend(results, warmup):
     d = []
     for result in results:
-        group = result['metric']['group']
+        group = result['metric'].get('consumergroup', "default")
         for value in result['values']:
             d.append({'group': group, 'timestamp': int(
                 value[0]), 'value': int(value[1]) if value[1] != 'NaN' else 0})
diff --git a/slo-checker/record-lag/resources/test-1-rep-success.json b/slo-checker/record-lag/resources/test-1-rep-success.json
index dfe11282720ebfcdd60582b7717da892bc85a923..09320c5f1eb0f96d847ddaa17cbd48c47a989155 100644
--- a/slo-checker/record-lag/resources/test-1-rep-success.json
+++ b/slo-checker/record-lag/resources/test-1-rep-success.json
@@ -3,7 +3,7 @@
         [
             {
                 "metric": {
-                    "group": "theodolite-uc1-application-0.0.1"
+                    "consumergroup": "theodolite-uc1-application-0.0.1"
                 },
                 "values": [
                     [
diff --git a/slo-checker/record-lag/resources/test-3-rep-success.json b/slo-checker/record-lag/resources/test-3-rep-success.json
index cf483f42f3783aecd1f428ac7bbbe2090c4cade0..e752430e09e00e6ea12128df44f2d687ba037a7a 100644
--- a/slo-checker/record-lag/resources/test-3-rep-success.json
+++ b/slo-checker/record-lag/resources/test-3-rep-success.json
@@ -3,7 +3,7 @@
         [
             {
                 "metric": {
-                    "group": "theodolite-uc1-application-0.0.1"
+                    "consumergroup": "theodolite-uc1-application-0.0.1"
                 },
                 "values": [
                     [
@@ -100,7 +100,7 @@
         [
             {
                 "metric": {
-                    "group": "theodolite-uc1-application-0.0.1"
+                    "consumergroup": "theodolite-uc1-application-0.0.1"
                 },
                 "values": [
                     [
@@ -193,7 +193,7 @@
         [
             {
                 "metric": {
-                    "group": "theodolite-uc1-application-0.0.1"
+                    "consumergroup": "theodolite-uc1-application-0.0.1"
                 },
                 "values": [
                     [
diff --git a/theodolite-benchmarks/beam-commons/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/beam-commons/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/beam-commons/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/beam-commons/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/beam-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/beam-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/beam-commons/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/beam-commons/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/beam-commons/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/beam-commons/build.gradle b/theodolite-benchmarks/beam-commons/build.gradle
index a809f6bc4b97d8d62b807243eddecda8a5de5032..64ac2bb51ae1e6d741749a81e5c6c9e296d14d68 100644
--- a/theodolite-benchmarks/beam-commons/build.gradle
+++ b/theodolite-benchmarks/beam-commons/build.gradle
@@ -13,21 +13,19 @@ repositories {
 }
 
 dependencies {
-  // These dependencies are used internally, and not exposed to consumers on their own compile classpath.
   implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true }
   implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true }
-  implementation 'com.google.code.gson:gson:2.8.2'
-  implementation 'com.google.guava:guava:24.1-jre'
 
-  implementation('org.apache.beam:beam-sdks-java-io-kafka:2.22.0'){
+  implementation group: 'org.apache.beam', name: 'beam-sdks-java-core', version: '2.35.0'
+  implementation('org.apache.beam:beam-sdks-java-io-kafka:2.35.0'){
     exclude group: 'org.apache.kafka', module: 'kafka-clients'
   }
+  implementation ('io.confluent:kafka-streams-avro-serde:5.3.2') 
+  
   implementation group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.30'
-  implementation group: 'org.apache.beam', name: 'beam-sdks-java-core', version: '2.22.0'
 
   runtimeOnly 'org.slf4j:slf4j-api:1.7.32'
   runtimeOnly 'org.slf4j:slf4j-jdk14:1.7.32'
 
-  // Use JUnit test framework
   testImplementation 'junit:junit:4.12'
 }
diff --git a/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/AbstractPipelineFactory.java b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/AbstractPipelineFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..f6dc64bb2c8f4deb0df6e48db23b0d62c6d86279
--- /dev/null
+++ b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/AbstractPipelineFactory.java
@@ -0,0 +1,74 @@
+package rocks.theodolite.benchmarks.commons.beam;
+
+import io.confluent.kafka.serializers.AbstractKafkaAvroSerDeConfig;
+import io.confluent.kafka.serializers.KafkaAvroDeserializerConfig;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.coders.CoderRegistry;
+import org.apache.beam.sdk.options.PipelineOptions;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.kafka.clients.consumer.ConsumerConfig;
+import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaActivePowerTimestampReader;
+
+/**
+ * Abstract factory class for creating Beam pipelines from a {@link Configuration} and
+ * {@link PipelineOptions}. Implementations may expand the {@link PipelineOptions}, construct a
+ * {@link Pipeline} and register coders.
+ */
+public abstract class AbstractPipelineFactory {
+
+  protected final Configuration config;
+
+  public AbstractPipelineFactory(final Configuration configuration) {
+    this.config = configuration;
+  }
+
+  /**
+   * Create a Pipeline with the configured {@link PipelineOptions}.
+   */
+  public final Pipeline create(final PipelineOptions options) {
+    this.expandOptions(options);
+    final Pipeline pipeline = Pipeline.create(options);
+    this.registerCoders(pipeline.getCoderRegistry());
+    this.constructPipeline(pipeline);
+    return pipeline;
+  }
+
+  protected abstract void expandOptions(final PipelineOptions options);
+
+  protected abstract void constructPipeline(Pipeline pipeline);
+
+  protected abstract void registerCoders(CoderRegistry registry);
+
+  protected KafkaActivePowerTimestampReader buildKafkaReader() {
+    final String inputTopic = this.config.getString(ConfigurationKeys.KAFKA_INPUT_TOPIC);
+    final String bootstrapServer = this.config.getString(ConfigurationKeys.KAFKA_BOOTSTRAP_SERVERS);
+
+    final Map<String, Object> consumerConfig = new HashMap<>();
+    consumerConfig.put(
+        ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,
+        this.config.getString(ConfigurationKeys.ENABLE_AUTO_COMMIT));
+    consumerConfig.put(
+        ConsumerConfig.MAX_POLL_RECORDS_CONFIG,
+        this.config.getString(ConfigurationKeys.MAX_POLL_RECORDS));
+    consumerConfig.put(
+        ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,
+        this.config.getString(ConfigurationKeys.AUTO_OFFSET_RESET));
+    consumerConfig.put(
+        AbstractKafkaAvroSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG,
+        this.config.getString(ConfigurationKeys.SCHEMA_REGISTRY_URL));
+    consumerConfig.put(
+        KafkaAvroDeserializerConfig.SPECIFIC_AVRO_READER_CONFIG,
+        this.config.getString(ConfigurationKeys.SPECIFIC_AVRO_READER));
+    consumerConfig.put(
+        ConsumerConfig.GROUP_ID_CONFIG,
+        this.config.getString(ConfigurationKeys.APPLICATION_NAME));
+
+    return new KafkaActivePowerTimestampReader(
+        bootstrapServer,
+        inputTopic,
+        consumerConfig);
+  }
+
+}
diff --git a/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/BeamService.java b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/BeamService.java
new file mode 100644
index 0000000000000000000000000000000000000000..0165fa644e1853353e73caeaf0b9d2df0f8e9aea
--- /dev/null
+++ b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/BeamService.java
@@ -0,0 +1,88 @@
+package rocks.theodolite.benchmarks.commons.beam;
+
+import java.io.IOException;
+import java.util.function.Function;
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.PipelineResult;
+import org.apache.beam.sdk.PipelineRunner;
+import org.apache.beam.sdk.options.PipelineOptions;
+import org.apache.beam.sdk.options.PipelineOptionsFactory;
+import org.apache.commons.configuration2.Configuration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import titan.ccp.common.configuration.ServiceConfigurations;
+
+/**
+ * A general Apache Beam-based microservice. It is configured by Beam pipeline, a Beam runner and
+ * additional configuration.
+ */
+public class BeamService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(BeamService.class);
+
+  private final Configuration config = ServiceConfigurations.createWithDefaults();
+  private final String applicationName = this.config.getString(ConfigurationKeys.APPLICATION_NAME);
+
+  private final AbstractPipelineFactory pipelineFactory;
+  private final PipelineOptions pipelineOptions;
+  private PipelineResult pipelineResult;
+
+  /**
+   * Create a new {@link BeamService}.
+   *
+   * @param pipelineFactoryFactory {@link Function} for creating an {@link AbstractPipelineFactory}
+   *        based on a {@link Configuration}.
+   * @param runner The Beam {@link PipelineRunner} to run this pipeline.
+   * @param args Arguments which are treated as {@link PipelineOptions}.
+   */
+  public BeamService(
+      final Function<Configuration, AbstractPipelineFactory> pipelineFactoryFactory,
+      final Class<? extends PipelineRunner<?>> runner,
+      final String... args) {
+    this.pipelineFactory = pipelineFactoryFactory.apply(this.config);
+    this.pipelineOptions = PipelineOptionsFactory.fromArgs(args).create();
+    this.pipelineOptions.setJobName(this.applicationName);
+    this.pipelineOptions.setRunner(runner);
+  }
+
+  /**
+   * Start this microservice by running the underlying Beam pipeline.
+   */
+  public void run() {
+    LOGGER.info("Constructing Beam pipeline with pipeline options: {}",
+        this.pipelineOptions.toString());
+    final Pipeline pipeline = this.pipelineFactory.create(this.pipelineOptions);
+    LOGGER.info("Starting BeamService {}.", this.applicationName);
+    this.pipelineResult = pipeline.run();
+  }
+
+  /**
+   * Start this microservice by running the underlying Beam pipeline and block until this process is
+   * terminated.
+   */
+  public void runStandalone() {
+    this.run();
+    Runtime.getRuntime().addShutdownHook(new Thread(() -> this.stop()));
+    this.pipelineResult.waitUntilFinish();
+  }
+
+  /**
+   * Stop this microservice by canceling the underlying Beam pipeline.
+   */
+  public void stop() {
+    LOGGER.info("Initiate shutdown of Beam service {}.", this.applicationName);
+    if (this.pipelineResult == null) {
+      throw new IllegalStateException("Cannot stop service since it has never been started.");
+    }
+    LOGGER.info("Stopping Beam pipeline.");
+    try {
+      this.pipelineResult.cancel();
+      this.pipelineResult = null; // NOPMD use null to indicate absence
+    } catch (final IOException e) {
+      throw new IllegalStateException(
+          "Stopping the service failed due to failed stop of Beam pipeline.", e);
+    }
+    LOGGER.info("Shutdown of Beam service {} complete.", this.applicationName);
+  }
+
+}
diff --git a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/ConfigurationKeys.java b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/ConfigurationKeys.java
similarity index 75%
rename from theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/ConfigurationKeys.java
rename to theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/ConfigurationKeys.java
index 1e4dc593c627282f5c6735a4d91e963d83af6865..c22c164f62ad22d3c18add75ad5115fd15fb8f14 100644
--- a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/ConfigurationKeys.java
+++ b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/ConfigurationKeys.java
@@ -1,4 +1,4 @@
-package theodolite.commons.beam;
+package rocks.theodolite.benchmarks.commons.beam;
 
 /**
  * Keys to access configuration parameters.
@@ -33,16 +33,17 @@ public final class ConfigurationKeys {
 
 
   // BEAM
-  public static final String ENABLE_AUTO_COMMIT_CONFIG = "enable.auto.commit.config";
+  public static final String ENABLE_AUTO_COMMIT = "enable.auto.commit";
 
-  public static final String AUTO_OFFSET_RESET_CONFIG = "auto.offset.reset.config";
+  public static final String MAX_POLL_RECORDS = "max.poll.records";
+
+  public static final String AUTO_OFFSET_RESET = "auto.offset.reset";
 
   public static final String SPECIFIC_AVRO_READER = "specific.avro.reader";
 
-  public static final String TRIGGER_INTERVAL  = "trigger.interval";
+  public static final String TRIGGER_INTERVAL = "trigger.interval";
 
 
-  private ConfigurationKeys() {
-  }
+  private ConfigurationKeys() {}
 
 }
diff --git a/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/ActivePowerRecordDeserializer.java b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/ActivePowerRecordDeserializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c8d3a4a847cf9422c4e364a31024fb3d0c3f87a
--- /dev/null
+++ b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/ActivePowerRecordDeserializer.java
@@ -0,0 +1,11 @@
+package rocks.theodolite.benchmarks.commons.beam.kafka;
+
+import io.confluent.kafka.streams.serdes.avro.SpecificAvroDeserializer;
+import org.apache.kafka.common.serialization.Deserializer;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * A Kafka {@link Deserializer} for typed Schema Registry {@link ActivePowerRecord}.
+ */
+public class ActivePowerRecordDeserializer extends SpecificAvroDeserializer<ActivePowerRecord> {
+}
diff --git a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/EventTimePolicy.java b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/EventTimePolicy.java
similarity index 94%
rename from theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/EventTimePolicy.java
rename to theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/EventTimePolicy.java
index e568968670b3ea51388f3e2a19da8f64bd7c5391..62e56341518839b96ad059e1c496ea1babb4674d 100644
--- a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/EventTimePolicy.java
+++ b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/EventTimePolicy.java
@@ -1,4 +1,4 @@
-package theodolite.commons.beam.kafka;
+package rocks.theodolite.benchmarks.commons.beam.kafka;
 
 import java.util.Optional;
 import org.apache.beam.sdk.io.kafka.KafkaRecord;
diff --git a/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/KafkaActivePowerTimestampReader.java b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/KafkaActivePowerTimestampReader.java
new file mode 100644
index 0000000000000000000000000000000000000000..e22d5c8eedcd545364511a1461208f30bcb0a75c
--- /dev/null
+++ b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/KafkaActivePowerTimestampReader.java
@@ -0,0 +1,52 @@
+package rocks.theodolite.benchmarks.commons.beam.kafka;
+
+import java.util.Map;
+import org.apache.beam.sdk.coders.AvroCoder;
+import org.apache.beam.sdk.io.kafka.KafkaIO;
+import org.apache.beam.sdk.transforms.PTransform;
+import org.apache.beam.sdk.values.KV;
+import org.apache.beam.sdk.values.PBegin;
+import org.apache.beam.sdk.values.PCollection;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * Simple {@link PTransform} that reads from Kafka using {@link KafkaIO} with event time.
+ */
+public class KafkaActivePowerTimestampReader
+    extends PTransform<PBegin, PCollection<KV<String, ActivePowerRecord>>> {
+
+  private static final long serialVersionUID = 2603286150183186115L;
+  private final PTransform<PBegin, PCollection<KV<String, ActivePowerRecord>>> reader;
+
+  /**
+   * Instantiates a {@link PTransform} that reads from Kafka with the given Configuration.
+   */
+  public KafkaActivePowerTimestampReader(
+      final String bootstrapServer,
+      final String inputTopic,
+      final Map<String, Object> consumerConfig) {
+    super();
+
+    // Check if bootstrap server and inputTopic are defined
+    if (bootstrapServer.isEmpty() || inputTopic.isEmpty()) {
+      throw new IllegalArgumentException("bootstrapServer or inputTopic missing");
+    }
+
+    this.reader = KafkaIO.<String, ActivePowerRecord>read().withBootstrapServers(bootstrapServer)
+        .withTopic(inputTopic).withKeyDeserializer(StringDeserializer.class)
+        .withValueDeserializerAndCoder(
+            ActivePowerRecordDeserializer.class,
+            AvroCoder.of(ActivePowerRecord.class))
+        .withConsumerConfigUpdates(consumerConfig)
+        .withTimestampPolicyFactory(
+            (tp, previousWatermark) -> new EventTimePolicy(previousWatermark))
+        .withoutMetadata();
+  }
+
+  @Override
+  public PCollection<KV<String, ActivePowerRecord>> expand(final PBegin input) {
+    return input.apply(this.reader);
+  }
+
+}
diff --git a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/KafkaGenericReader.java b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/KafkaGenericReader.java
similarity index 65%
rename from theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/KafkaGenericReader.java
rename to theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/KafkaGenericReader.java
index 83336b5a4c2451ef4bffefbd60ad9d52fccd9c17..000ddcdccd90cf3bc4f0cdaabe004ce74bef5dec 100644
--- a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/KafkaGenericReader.java
+++ b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/KafkaGenericReader.java
@@ -1,4 +1,4 @@
-package theodolite.commons.beam.kafka;
+package rocks.theodolite.benchmarks.commons.beam.kafka;
 
 import java.util.Map;
 import org.apache.beam.sdk.io.kafka.KafkaIO;
@@ -6,6 +6,7 @@ import org.apache.beam.sdk.transforms.PTransform;
 import org.apache.beam.sdk.values.KV;
 import org.apache.beam.sdk.values.PBegin;
 import org.apache.beam.sdk.values.PCollection;
+import org.apache.kafka.common.serialization.Deserializer;
 
 /**
  * Simple {@link PTransform} that read from Kafka using {@link KafkaIO}.
@@ -13,8 +14,7 @@ import org.apache.beam.sdk.values.PCollection;
  * @param <K> Type of the Key.
  * @param <V> Type of the Value.
  */
-public class KafkaGenericReader<K, V> extends
-    PTransform<PBegin, PCollection<KV<K, V>>> {
+public class KafkaGenericReader<K, V> extends PTransform<PBegin, PCollection<KV<K, V>>> {
 
   private static final long serialVersionUID = 2603286150183186115L;
   private final PTransform<PBegin, PCollection<KV<K, V>>> reader;
@@ -22,14 +22,12 @@ public class KafkaGenericReader<K, V> extends
   /**
    * Instantiates a {@link PTransform} that reads from Kafka with the given Configuration.
    */
-  public KafkaGenericReader(final String bootstrapServer, final String inputTopic,
-                            final Map<String, Object> consumerConfig,
-                            final Class<? extends
-                                org.apache.kafka.common.serialization.Deserializer<K>>
-                                  keyDeserializer,
-                            final Class<? extends
-                                org.apache.kafka.common.serialization.Deserializer<V>>
-                                  valueDeserializer) {
+  public KafkaGenericReader(
+      final String bootstrapServer,
+      final String inputTopic,
+      final Map<String, Object> consumerConfig,
+      final Class<? extends Deserializer<K>> keyDeserializer,
+      final Class<? extends Deserializer<V>> valueDeserializer) {
     super();
 
     // Check if boostrap server and inputTopic are defined
@@ -37,7 +35,7 @@ public class KafkaGenericReader<K, V> extends
       throw new IllegalArgumentException("bootstrapServer or inputTopic missing");
     }
 
-    reader =
+    this.reader =
         KafkaIO.<K, V>read()
             .withBootstrapServers(bootstrapServer)
             .withTopic(inputTopic)
diff --git a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/KafkaWriterTransformation.java b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/KafkaWriterTransformation.java
similarity index 50%
rename from theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/KafkaWriterTransformation.java
rename to theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/KafkaWriterTransformation.java
index 0a3867e71479e36ce30a9f222dfd0a7d473bd209..e9131b513001bf8756495a6aecfe72456959f0c6 100644
--- a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/KafkaWriterTransformation.java
+++ b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/KafkaWriterTransformation.java
@@ -1,5 +1,6 @@
-package theodolite.commons.beam.kafka;
+package rocks.theodolite.benchmarks.commons.beam.kafka;
 
+import java.util.Map;
 import org.apache.beam.sdk.io.kafka.KafkaIO;
 import org.apache.beam.sdk.transforms.PTransform;
 import org.apache.beam.sdk.values.KV;
@@ -9,23 +10,35 @@ import org.apache.kafka.common.serialization.Serializer;
 import org.apache.kafka.common.serialization.StringSerializer;
 
 /**
- * Wrapper for a Kafka writing Transformation
- * where the value type can be generic.
+ * Wrapper for a Kafka writing Transformation where the value type can be generic.
+ *
  * @param <T> type of the value.
  */
-public class KafkaWriterTransformation<T> extends
-    PTransform<PCollection<KV<String, T>>, PDone> {
+public class KafkaWriterTransformation<T> extends PTransform<PCollection<KV<String, T>>, PDone> {
 
   private static final long serialVersionUID = 3171423303843174723L;
   private final PTransform<PCollection<KV<String, T>>, PDone> writer;
 
   /**
-   * Creates a new kafka writer transformation.
+   * Creates a new Kafka writer transformation.
    */
-  public KafkaWriterTransformation(final String bootstrapServer, final String outputTopic,
-                                   final Class<? extends Serializer<T>> valueSerializer) {
+  public KafkaWriterTransformation(
+      final String bootstrapServer,
+      final String outputTopic,
+      final Class<? extends Serializer<T>> valueSerializer) {
+    this(bootstrapServer, outputTopic, valueSerializer, Map.of());
+  }
+
+  /**
+   * Creates a new Kafka writer transformation.
+   */
+  public KafkaWriterTransformation(
+      final String bootstrapServer,
+      final String outputTopic,
+      final Class<? extends Serializer<T>> valueSerializer,
+      final Map<String, Object> producerConfig) {
     super();
-    // Check if boostrap server and outputTopic are defined
+    // Check if bootstrap server and outputTopic are defined
     if (bootstrapServer.isEmpty() || outputTopic.isEmpty()) {
       throw new IllegalArgumentException("bootstrapServer or outputTopic missing");
     }
@@ -34,7 +47,8 @@ public class KafkaWriterTransformation<T> extends
         .withBootstrapServers(bootstrapServer)
         .withTopic(outputTopic)
         .withKeySerializer(StringSerializer.class)
-        .withValueSerializer(valueSerializer);
+        .withValueSerializer(valueSerializer)
+        .withProducerConfigUpdates(producerConfig);
 
   }
 
diff --git a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/AbstractBeamService.java b/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/AbstractBeamService.java
deleted file mode 100644
index 03c5ca1daa7ffab71a4d08c04f677d7412e3a2be..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/AbstractBeamService.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package theodolite.commons.beam;
-
-import org.apache.beam.sdk.options.PipelineOptions;
-import org.apache.beam.sdk.options.PipelineOptionsFactory;
-import org.apache.commons.configuration2.Configuration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import titan.ccp.common.configuration.ServiceConfigurations;
-
-/**
- * Abstraction of a Beam microservice.
- * Encapsulates the corresponding {@link PipelineOptions} and the beam Runner.
- */
-public class AbstractBeamService {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(AbstractBeamService.class);
-
-  // Beam Pipeline
-  protected PipelineOptions options;
-
-  // Application Configurations
-  private final Configuration config = ServiceConfigurations.createWithDefaults();
-  private final String applicationName =
-      config.getString(ConfigurationKeys.APPLICATION_NAME);
-
-
-  /**
-   * Creates AbstractBeamService with options.
-   */
-  public AbstractBeamService(final String[] args) { //NOPMD
-    super();
-    LOGGER.info("Pipeline options:");
-    for (final String s : args) {
-      LOGGER.info("{}", s);
-    }
-    options = PipelineOptionsFactory.fromArgs(args).create();
-    options.setJobName(applicationName);
-    LOGGER.info("Starting BeamService with PipelineOptions {}:", this.options.toString());
-  }
-
-  public Configuration getConfig() {
-    return config;
-  }
-
-}
diff --git a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/AbstractPipeline.java b/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/AbstractPipeline.java
deleted file mode 100644
index c936ce918c10f3c500cdd26f7e057cd7b6c555b6..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/AbstractPipeline.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package theodolite.commons.beam;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.apache.beam.sdk.Pipeline;
-import org.apache.beam.sdk.options.PipelineOptions;
-import org.apache.commons.configuration2.Configuration;
-import org.apache.kafka.clients.consumer.ConsumerConfig;
-
-/**
- * Abstraction of a Beam {@link Pipeline}.
- */
-public class AbstractPipeline extends Pipeline {
-
-  protected final String inputTopic;
-  protected final String bootstrapServer;
-  // Application Configurations
-  private final Configuration config;
-
-  protected AbstractPipeline(final PipelineOptions options, final Configuration config) {
-    super(options);
-    this.config = config;
-
-    inputTopic = config.getString(ConfigurationKeys.KAFKA_INPUT_TOPIC);
-    bootstrapServer = config.getString(ConfigurationKeys.KAFKA_BOOTSTRAP_SERVERS);
-  }
-
-  /**
-   * Builds a simple configuration for a Kafka consumer transformation.
-   *
-   * @return the build configuration.
-   */
-  public Map<String, Object> buildConsumerConfig() {
-    final Map<String, Object> consumerConfig = new HashMap<>();
-    consumerConfig.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,
-        config.getString(ConfigurationKeys.ENABLE_AUTO_COMMIT_CONFIG));
-    consumerConfig.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,
-        config
-            .getString(ConfigurationKeys.AUTO_OFFSET_RESET_CONFIG));
-    consumerConfig.put("schema.registry.url",
-        config.getString(ConfigurationKeys.SCHEMA_REGISTRY_URL));
-
-    consumerConfig.put("specific.avro.reader",
-        config.getString(ConfigurationKeys.SPECIFIC_AVRO_READER));
-
-    final String applicationName = config.getString(ConfigurationKeys.APPLICATION_NAME);
-    consumerConfig.put(ConsumerConfig.GROUP_ID_CONFIG, applicationName);
-    return consumerConfig;
-  }
-}
diff --git a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/KafkaActivePowerRecordReader.java b/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/KafkaActivePowerRecordReader.java
deleted file mode 100644
index f102bee41d66c251ecb66418dd3b90dced32cffb..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/KafkaActivePowerRecordReader.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package theodolite.commons.beam.kafka;
-
-import io.confluent.kafka.serializers.KafkaAvroDeserializer;
-import java.util.Map;
-import org.apache.beam.sdk.coders.AvroCoder;
-import org.apache.beam.sdk.io.kafka.KafkaIO;
-import org.apache.beam.sdk.transforms.PTransform;
-import org.apache.beam.sdk.values.KV;
-import org.apache.beam.sdk.values.PBegin;
-import org.apache.beam.sdk.values.PCollection;
-import org.apache.kafka.common.serialization.StringDeserializer;
-import titan.ccp.model.records.ActivePowerRecord;
-
-/**
- * Simple {@link PTransform} that read from Kafka using {@link KafkaIO}.
- */
-public class KafkaActivePowerRecordReader extends
-    PTransform<PBegin, PCollection<KV<String, ActivePowerRecord>>> {
-
-  private static final long serialVersionUID = 2603286150183186115L;
-  private final PTransform<PBegin, PCollection<KV<String, ActivePowerRecord>>> reader;
-
-
-  /**
-   * Instantiates a {@link PTransform} that reads from Kafka with the given Configuration.
-   */
-  public KafkaActivePowerRecordReader(final String bootstrapServer, final String inputTopic,
-                                      final Map<String, Object> consumerConfig) {
-    super();
-
-    if (bootstrapServer == null) {
-      throw new IllegalArgumentException("bootstrapServer is null");
-    }
-
-    if (inputTopic == null) {
-      throw new IllegalArgumentException("inputTopic is null");
-    }
-
-    // Check if boostrap server and inputTopic are defined
-    if (bootstrapServer.isEmpty() || inputTopic.isEmpty()) {
-      throw new IllegalArgumentException("bootstrapServer or inputTopic missing");
-    }
-
-
-    reader =
-        KafkaIO.<String, ActivePowerRecord>read()
-            .withBootstrapServers(bootstrapServer)
-            .withTopic(inputTopic)
-            .withKeyDeserializer(StringDeserializer.class)
-            .withValueDeserializerAndCoder((Class) KafkaAvroDeserializer.class,
-                AvroCoder.of(ActivePowerRecord.class))
-            .withConsumerConfigUpdates(consumerConfig)
-            .withoutMetadata();
-  }
-
-  @Override
-  public PCollection<KV<String, ActivePowerRecord>> expand(final PBegin input) {
-    return input.apply(this.reader);
-  }
-
-}
diff --git a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/KafkaActivePowerTimestampReader.java b/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/KafkaActivePowerTimestampReader.java
deleted file mode 100644
index 732afe9a0c1d4bdfea876025fceea0c5da1310fe..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/beam-commons/src/main/java/theodolite/commons/beam/kafka/KafkaActivePowerTimestampReader.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package theodolite.commons.beam.kafka;
-
-import io.confluent.kafka.serializers.KafkaAvroDeserializer;
-import java.util.Map;
-import org.apache.beam.sdk.coders.AvroCoder;
-import org.apache.beam.sdk.io.kafka.KafkaIO;
-import org.apache.beam.sdk.transforms.PTransform;
-import org.apache.beam.sdk.values.KV;
-import org.apache.beam.sdk.values.PBegin;
-import org.apache.beam.sdk.values.PCollection;
-import org.apache.kafka.common.serialization.StringDeserializer;
-import titan.ccp.model.records.ActivePowerRecord;
-
-/**
- * Simple {@link PTransform} that read from Kafka using {@link KafkaIO}.
- * Has additional a TimestampPolicy.
- */
-public class KafkaActivePowerTimestampReader extends
-    PTransform<PBegin, PCollection<KV<String, ActivePowerRecord>>> {
-
-  private static final long serialVersionUID = 2603286150183186115L;
-  private final PTransform<PBegin, PCollection<KV<String, ActivePowerRecord>>> reader;
-
-
-  /**
-   * Instantiates a {@link PTransform} that reads from Kafka with the given Configuration.
-   */
-  public KafkaActivePowerTimestampReader(final String bootstrapServer, final String inputTopic,
-                                         final Map<String, Object> consumerConfig) {
-    super();
-
-    // Check if boostrap server and inputTopic are defined
-    if (bootstrapServer.isEmpty() || inputTopic.isEmpty()) {
-      throw new IllegalArgumentException("bootstrapServer or inputTopic missing");
-    }
-
-    reader =
-        KafkaIO.<String, ActivePowerRecord>read()
-            .withBootstrapServers(bootstrapServer)
-            .withTopic(inputTopic)
-            .withKeyDeserializer(StringDeserializer.class)
-            .withValueDeserializerAndCoder((Class) KafkaAvroDeserializer.class,
-                AvroCoder.of(ActivePowerRecord.class))
-            .withConsumerConfigUpdates(consumerConfig)
-            // Set TimeStampPolicy for event time
-            .withTimestampPolicyFactory(
-                (tp, previousWaterMark) -> new EventTimePolicy(previousWaterMark))
-            .withoutMetadata();
-  }
-
-  @Override
-  public PCollection<KV<String, ActivePowerRecord>> expand(final PBegin input) {
-    return input.apply(this.reader);
-  }
-
-}
diff --git a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.flink.gradle b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.flink.gradle
index eb9bda1f84c4f20568fca1498462dff9082ea1fa..02bf925f8dc29456f9eeaddeef800d2edcf837f8 100644
--- a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.flink.gradle
+++ b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.flink.gradle
@@ -3,6 +3,6 @@ plugins {
 }
 
 dependencies {
-    implementation group: 'org.apache.beam', name: 'beam-runners-flink-1.12', version: '2.27.0'
-    implementation group: 'org.apache.flink', name: 'flink-statebackend-rocksdb_2.11', version: '1.12.0'
+    implementation group: 'org.apache.beam', name: 'beam-runners-flink-1.13', version: '2.35.0'
+    implementation group: 'org.apache.flink', name: 'flink-statebackend-rocksdb_2.11', version: '1.13.0'
 }
\ No newline at end of file
diff --git a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.gradle b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.gradle
index 41d1ae4f2bdfa358aca3fca2b91ea2b57e4c3405..5849bd93221794d135f1c6cb3bcb62d2174724b5 100644
--- a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.gradle
+++ b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.gradle
@@ -18,13 +18,12 @@ repositories {
     }
 }
 
-def apacheBeamVersion =  '2.22.0' //'2.27.0' // '2.34.0'
+def apacheBeamVersion =  '2.35.0'
 
 dependencies {
     // These dependencies are used internally, and not exposed to consumers on their own compile classpath.
     implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true }
     implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true }
-    implementation 'com.google.code.gson:gson:2.8.2'
     implementation 'com.google.guava:guava:24.1-jre'
     implementation 'org.slf4j:slf4j-simple:1.7.25'
     implementation project(':beam-commons')
diff --git a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.samza.gradle b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.samza.gradle
index 73e916ccc867b9b3316776192f0dab56fa0710f0..44c59317472686cae88d6992382ae081c9b64ace 100644
--- a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.samza.gradle
+++ b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.samza.gradle
@@ -3,7 +3,8 @@ plugins {
 }
 
 dependencies {
-    implementation('org.apache.beam:beam-runners-samza:2.22.0') {
+    implementation('org.apache.beam:beam-runners-samza:2.35.0') {
         exclude group: 'org.apache.samza', module: 'samza-yarn_2.11'
     }
+    implementation 'org.apache.samza:samza-kafka_2.11:1.5.0'
 }
\ No newline at end of file
diff --git a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.flink.gradle b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.flink.gradle
index f5e93dd88d2234f8a9b0d6fea880f47d652dccfa..7671e602211b6d9e923a3b2a4c87f40fff84c6ec 100644
--- a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.flink.gradle
+++ b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.flink.gradle
@@ -20,7 +20,7 @@ shadowJar {
 tasks.distZip.enabled = false
 
 ext {
-  flinkVersion = '1.12.2'
+  flinkVersion = '1.13.5'
   scalaBinaryVersion = '2.12'
 }
 
@@ -41,7 +41,6 @@ dependencies {
 
     implementation 'org.apache.kafka:kafka-clients:2.2.0'
     implementation 'com.google.guava:guava:30.1-jre'
-    implementation 'com.google.code.gson:gson:2.8.2'
     implementation 'org.slf4j:slf4j-simple:1.6.1'
     implementation project(':flink-commons')
 
diff --git a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.hazelcastjet.gradle b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.hazelcastjet.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..b092c97cf0e79895d4d6aafc594979b8f48dd167
--- /dev/null
+++ b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.hazelcastjet.gradle
@@ -0,0 +1,45 @@
+plugins {
+  // common java conventions
+  id 'theodolite.java-conventions'
+
+  // make executable
+  id 'application'
+}
+
+repositories {
+  mavenCentral()
+  maven {
+    url "https://oss.sonatype.org/content/repositories/snapshots/"
+  }
+  maven {
+    url 'https://packages.confluent.io/maven/'
+  }
+}
+
+dependencies {
+  implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true }
+  implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true }
+  implementation 'com.google.guava:guava:24.1-jre'
+  implementation 'org.slf4j:slf4j-api:1.7.30'
+  implementation 'org.slf4j:slf4j-simple:1.7.30'
+
+
+  implementation 'io.confluent:kafka-avro-serializer:5.3.0'
+
+  implementation 'com.hazelcast.jet:hazelcast-jet:4.5'
+  implementation 'com.hazelcast.jet:hazelcast-jet-kafka:4.5'
+  implementation 'com.hazelcast:hazelcast-kubernetes:2.2.2'
+ 	
+  implementation project(':hazelcastjet-commons')
+
+  testImplementation("junit:junit:4.13.2")
+  testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.8.2")
+
+  testImplementation 'com.hazelcast:hazelcast:4.2:tests'
+  testImplementation 'com.hazelcast.jet:hazelcast-jet-core:4.5:tests'
+
+}
+
+test {
+  useJUnitPlatform()
+}
diff --git a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.kstreams.gradle b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.kstreams.gradle
index da2d42176ac0ddc9a157f843e3268b37ac4397e2..bf533915a8fdf4a712754857702373264a30f80a 100644
--- a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.kstreams.gradle
+++ b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.kstreams.gradle
@@ -22,8 +22,7 @@ dependencies {
     // These dependencies are used internally, and not exposed to consumers on their own compile classpath.
     implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true }
     implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true }
-    implementation 'org.apache.kafka:kafka-streams:2.6.0' // enable TransformerSuppliers
-    implementation 'com.google.code.gson:gson:2.8.2'
+    implementation 'org.apache.kafka:kafka-streams:3.1.0'
     implementation 'com.google.guava:guava:24.1-jre'
     implementation 'org.slf4j:slf4j-simple:1.7.25'
     implementation project(':kstreams-commons')
diff --git a/theodolite-benchmarks/config/spotbugs-exclude-filter.xml b/theodolite-benchmarks/config/spotbugs-exclude-filter.xml
index 38cd4b6914b3f0cbdeac2a22bf29ce0d7cf487ee..4bc9e048fb20e27feb793d4c6c398345cd599cff 100644
--- a/theodolite-benchmarks/config/spotbugs-exclude-filter.xml
+++ b/theodolite-benchmarks/config/spotbugs-exclude-filter.xml
@@ -5,4 +5,7 @@
     <Rank value="16" />
   </Match>
 
+  <!-- Temporary disabled due to potential false positive reported in https://github.com/spotbugs/spotbugs/issues/1923. -->
+  <Bug code="NP" />
+
 </FindBugsFilter>
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/install-configmaps.sh b/theodolite-benchmarks/definitions/install-configmaps.sh
index 841a293bbb77c4960a2532a13a009a42227223d3..e6630ca08154631a395c151fac376859fc885495 100755
--- a/theodolite-benchmarks/definitions/install-configmaps.sh
+++ b/theodolite-benchmarks/definitions/install-configmaps.sh
@@ -4,12 +4,30 @@ kubectl create configmap benchmark-resources-uc2-flink --from-file uc2-flink/res
 kubectl create configmap benchmark-resources-uc3-flink --from-file uc3-flink/resources
 kubectl create configmap benchmark-resources-uc4-flink --from-file uc4-flink/resources
 
+kubectl create configmap benchmark-resources-uc1-hazelcastjet --from-file uc1-hazelcastjet/resources
+kubectl create configmap benchmark-resources-uc2-hazelcastjet --from-file uc2-hazelcastjet/resources
+kubectl create configmap benchmark-resources-uc3-hazelcastjet --from-file uc3-hazelcastjet/resources
+kubectl create configmap benchmark-resources-uc4-hazelcastjet --from-file uc4-hazelcastjet/resources
+
+
 # Kafka Streams
 kubectl create configmap benchmark-resources-uc1-kstreams --from-file uc1-kstreams/resources
 kubectl create configmap benchmark-resources-uc2-kstreams --from-file uc2-kstreams/resources
 kubectl create configmap benchmark-resources-uc3-kstreams --from-file uc3-kstreams/resources
 kubectl create configmap benchmark-resources-uc4-kstreams --from-file uc4-kstreams/resources
 
+# Beam Flink
+kubectl create configmap benchmark-resources-uc1-beam-flink --from-file uc1-beam-flink/resources
+kubectl create configmap benchmark-resources-uc2-beam-flink --from-file uc2-beam-flink/resources
+kubectl create configmap benchmark-resources-uc3-beam-flink --from-file uc3-beam-flink/resources
+kubectl create configmap benchmark-resources-uc4-beam-flink --from-file uc4-beam-flink/resources
+
+# Beam Samza
+kubectl create configmap benchmark-resources-uc1-beam-samza --from-file uc1-beam-samza/resources
+kubectl create configmap benchmark-resources-uc2-beam-samza --from-file uc2-beam-samza/resources
+kubectl create configmap benchmark-resources-uc3-beam-samza --from-file uc3-beam-samza/resources
+kubectl create configmap benchmark-resources-uc4-beam-samza --from-file uc4-beam-samza/resources
+
 # Load Generator
 kubectl create configmap benchmark-resources-uc1-load-generator --from-file uc1-load-generator/resources
 kubectl create configmap benchmark-resources-uc2-load-generator --from-file uc2-load-generator/resources
diff --git a/theodolite-benchmarks/definitions/uc1-beam-flink/resources/flink-configuration-configmap.yaml b/theodolite-benchmarks/definitions/uc1-beam-flink/resources/flink-configuration-configmap.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..36178e2bebdac96b8648bd6c299009aa49d3fff6
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-beam-flink/resources/flink-configuration-configmap.yaml
@@ -0,0 +1,66 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: flink-config
+  labels:
+    app: flink
+data:
+  flink-conf.yaml: |+
+    jobmanager.rpc.address: flink-jobmanager
+    taskmanager.numberOfTaskSlots: 1 #TODO
+    #blob.server.port: 6124
+    #jobmanager.rpc.port: 6123
+    #taskmanager.rpc.port: 6122
+    #queryable-state.proxy.ports: 6125
+    #jobmanager.memory.process.size: 4Gb
+    #taskmanager.memory.process.size: 4Gb
+    #parallelism.default: 1 #TODO
+    metrics.reporter.prom.class: org.apache.flink.metrics.prometheus.PrometheusReporter
+    metrics.reporter.prom.interval: 10 SECONDS
+    taskmanager.network.detailed-metrics: true
+  # -> gives metrics about inbound/outbound network queue lengths
+  log4j-console.properties: |+
+    # This affects logging for both user code and Flink
+    rootLogger.level = INFO
+    rootLogger.appenderRef.console.ref = ConsoleAppender
+    rootLogger.appenderRef.rolling.ref = RollingFileAppender
+
+    # Uncomment this if you want to _only_ change Flink's logging
+    #logger.flink.name = org.apache.flink
+    #logger.flink.level = INFO
+
+    # The following lines keep the log level of common libraries/connectors on
+    # log level INFO. The root logger does not override this. You have to manually
+    # change the log levels here.
+    logger.akka.name = akka
+    logger.akka.level = INFO
+    logger.kafka.name= org.apache.kafka
+    logger.kafka.level = INFO
+    logger.hadoop.name = org.apache.hadoop
+    logger.hadoop.level = INFO
+    logger.zookeeper.name = org.apache.zookeeper
+    logger.zookeeper.level = INFO
+
+    # Log all infos to the console
+    appender.console.name = ConsoleAppender
+    appender.console.type = CONSOLE
+    appender.console.layout.type = PatternLayout
+    appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n
+
+    # Log all infos in the given rolling file
+    appender.rolling.name = RollingFileAppender
+    appender.rolling.type = RollingFile
+    appender.rolling.append = false
+    appender.rolling.fileName = ${sys:log.file}
+    appender.rolling.filePattern = ${sys:log.file}.%i
+    appender.rolling.layout.type = PatternLayout
+    appender.rolling.layout.pattern = %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n
+    appender.rolling.policies.type = Policies
+    appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
+    appender.rolling.policies.size.size=100MB
+    appender.rolling.strategy.type = DefaultRolloverStrategy
+    appender.rolling.strategy.max = 10
+
+    # Suppress the irrelevant (wrong) warnings from the Netty channel handler
+    logger.netty.name = org.apache.flink.shaded.akka.org.jboss.netty.channel.DefaultChannelPipeline
+    logger.netty.level = OFF
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc1-beam-flink/resources/jobmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc1-beam-flink/resources/jobmanager-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c1fb35cbfb67efa5b4e41787c342374e835a1f3e
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-beam-flink/resources/jobmanager-deployment.yaml
@@ -0,0 +1,97 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: flink-jobmanager
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: flink
+      component: jobmanager
+  template:
+    metadata:
+      labels:
+        app: flink
+        component: jobmanager
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: jobmanager
+          image: ghcr.io/cau-se/theodolite-uc1-beam-flink:latest
+          args: ["standalone-job", "--job-classname", "rocks.theodolite.benchmarks.uc1.beam.flink.Uc1BeamFlink",
+                  "--parallelism=$(PARALLELISM)",
+                  "--disableMetrics=true",
+                  "--fasterCopy"]
+          # optional arguments: ["--job-id", "<job id>", "--fromSavepoint", "/path/to/savepoint", "--allowNonRestoredState"]
+          env:
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS
+              value: "100"
+            - name: CHECKPOINTING
+              value: "false"
+            - name: PARALLELISM
+              value: "1"
+            - name: "FLINK_STATE_BACKEND"
+              value: "rocksdb"
+            - name: JOB_MANAGER_RPC_ADDRESS
+              value: "flink-jobmanager"
+            - name: FLINK_PROPERTIES
+              value: |+
+                blob.server.port: 6124
+                jobmanager.rpc.port: 6123
+                taskmanager.rpc.port: 6122
+                queryable-state.proxy.ports: 6125
+                jobmanager.memory.process.size: 4Gb
+                taskmanager.memory.process.size: 4Gb
+                parallelism.default: 1 #TODO
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
+          ports:
+            - containerPort: 6123
+              name: rpc
+            - containerPort: 6124
+              name: blob-server
+            - containerPort: 8081
+              name: webui
+            - containerPort: 9249
+              name: metrics
+          livenessProbe:
+            tcpSocket:
+              port: 6123
+            initialDelaySeconds: 30
+            periodSeconds: 60
+          # volumeMounts:
+          #   - name: flink-config-volume-rw
+          #     mountPath: /opt/flink/conf
+#            - name: job-artifacts-volume
+#              mountPath: /opt/flink/usrlib
+          securityContext:
+            runAsUser: 9999  # refers to user _flink_ from official flink image, change if necessary
+      # initContainers:
+      #   - name: init-jobmanager
+      #     image: busybox:1.28
+      #     command: ['cp', '-a', '/flink-config/.', '/flink-config-rw/']
+      #     volumeMounts:
+      #       - name: flink-config-volume
+      #         mountPath: /flink-config/
+      #       - name: flink-config-volume-rw
+      #         mountPath: /flink-config-rw/
+      # volumes:
+      #   - name: flink-config-volume
+      #     configMap:
+      #       name: flink-config
+      #       items:
+      #         - key: flink-conf.yaml
+      #           path: flink-conf.yaml
+      #         - key: log4j-console.properties
+      #           path: log4j-console.properties
+      #   - name: flink-config-volume-rw
+      #     emptyDir: {}
+#        - name: job-artifacts-volume
+#          hostPath:
+#            path: /host/path/to/job/artifacts
diff --git a/theodolite-benchmarks/definitions/uc1-beam-flink/resources/jobmanager-rest-service.yaml b/theodolite-benchmarks/definitions/uc1-beam-flink/resources/jobmanager-rest-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..3d74aaf7f625c6922e2e1b4f20c19e50a39b68ac
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-beam-flink/resources/jobmanager-rest-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: flink-jobmanager-rest
+spec:
+  type: NodePort
+  ports:
+    - name: rest
+      port: 8081
+      targetPort: 8081
+      nodePort: 30081
+  selector:
+    app: flink
+    component: jobmanager
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc1-beam-flink/resources/jobmanager-service.yaml b/theodolite-benchmarks/definitions/uc1-beam-flink/resources/jobmanager-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e2ff5d9898eb1ebf5db9a827472a47514ab1473c
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-beam-flink/resources/jobmanager-service.yaml
@@ -0,0 +1,20 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: flink-jobmanager
+  labels:
+    app: flink
+spec:
+  type: ClusterIP
+  ports:
+    - name: rpc
+      port: 6123
+    - name: blob-server
+      port: 6124
+    - name: webui
+      port: 8081
+    - name: metrics
+      port: 9249
+  selector:
+    app: flink
+    component: jobmanager
\ No newline at end of file
diff --git a/helm/templates/kafka/service-monitor.yaml b/theodolite-benchmarks/definitions/uc1-beam-flink/resources/service-monitor.yaml
similarity index 51%
rename from helm/templates/kafka/service-monitor.yaml
rename to theodolite-benchmarks/definitions/uc1-beam-flink/resources/service-monitor.yaml
index 68fd5f7599d36187fa7c4dee2fab211eb263c67d..02f78823c627e27ddfe1db5eac3f6a7f7a7f1bf8 100644
--- a/helm/templates/kafka/service-monitor.yaml
+++ b/theodolite-benchmarks/definitions/uc1-beam-flink/resources/service-monitor.yaml
@@ -1,16 +1,14 @@
-{{- if .Values.kafkaClient.enabled -}}
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
 metadata:
   labels:
-    app: cp-kafka
+    app: flink
     appScope: titan-ccp
-  name: {{ template "theodolite.fullname" . }}-cp-kafka
+  name: flink
 spec:
   selector:
     matchLabels:
-      app: cp-kafka
+        app: flink
   endpoints:
     - port: metrics
-      interval: 7s
-{{- end}}
+      interval: 10s
diff --git a/theodolite-benchmarks/definitions/uc1-beam-flink/resources/taskmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc1-beam-flink/resources/taskmanager-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7d70908589cfa2124af64cf3c671ed62c00b1be6
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-beam-flink/resources/taskmanager-deployment.yaml
@@ -0,0 +1,88 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: flink-taskmanager
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: flink
+      component: taskmanager
+  template:
+    metadata:
+      labels:
+        app: flink
+        component: taskmanager
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: taskmanager
+          image: ghcr.io/cau-se/theodolite-uc1-beam-flink:latest
+          args: ["taskmanager"]
+          env:
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS
+              value: "100"
+            - name: CHECKPOINTING
+              value: "false"
+            # - name: PARALLELISM
+            #   value: "1"
+            - name: "FLINK_STATE_BACKEND"
+              value: "rocksdb"
+            - name: JOB_MANAGER_RPC_ADDRESS
+              value: "flink-jobmanager"
+            # - name: TASK_MANAGER_NUMBER_OF_TASK_SLOTS
+            #   value: "1" #TODO
+            # - name: FLINK_PROPERTIES
+            #   value: |+
+            #     blob.server.port: 6124
+            #     jobmanager.rpc.port: 6123
+            #     taskmanager.rpc.port: 6122
+            #     queryable-state.proxy.ports: 6125
+            #     jobmanager.memory.process.size: 4Gb
+            #     taskmanager.memory.process.size: 4Gb
+            #     #parallelism.default: 1 #TODO
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
+          ports:
+            - containerPort: 6122
+              name: rpc
+            - containerPort: 6125
+              name: query-state
+            - containerPort: 9249
+              name: metrics
+          # livenessProbe:
+          #   tcpSocket:
+          #     port: 6122
+          #   initialDelaySeconds: 30
+          #   periodSeconds: 60
+          # volumeMounts:
+          #   - name: flink-config-volume-rw
+          #     mountPath: /opt/flink/conf/
+          securityContext:
+            runAsUser: 9999  # refers to user _flink_ from official flink image, change if necessary
+      # initContainers:
+      #   - name: init-taskmanager
+      #     image: busybox:1.28
+      #     command: ['cp', '-a', '/flink-config/.', '/flink-config-rw/']
+      #     volumeMounts:
+      #       - name: flink-config-volume
+      #         mountPath: /flink-config/
+      #       - name: flink-config-volume-rw
+      #         mountPath: /flink-config-rw/
+      # volumes:
+      #   - name: flink-config-volume
+      #     configMap:
+      #       name: flink-config
+      #       items:
+      #         - key: flink-conf.yaml
+      #           path: flink-conf.yaml
+      #         - key: log4j-console.properties
+      #           path: log4j-console.properties
+      #   - name: flink-config-volume-rw
+      #     emptyDir: {}
diff --git a/theodolite-benchmarks/definitions/uc1-beam-flink/resources/taskmanager-service.yaml b/theodolite-benchmarks/definitions/uc1-beam-flink/resources/taskmanager-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a2e27f64af1cfd1a26da142b8a50bb41c8ba5fcb
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-beam-flink/resources/taskmanager-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: flink-taskmanager
+  labels:
+    app: flink
+spec:
+  type: ClusterIP
+  ports:
+    - name: metrics
+      port: 9249
+  selector:
+    app: flink
+    component: taskmanager
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc1-beam-flink/uc1-beam-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc1-beam-flink/uc1-beam-flink-benchmark-operator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..2e110abfc13e1537792da381de2260fb3adbd606
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-beam-flink/uc1-beam-flink-benchmark-operator.yaml
@@ -0,0 +1,57 @@
+apiVersion: theodolite.com/v1
+kind: benchmark
+metadata:
+  name: uc1-beam-flink
+spec:
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc1-beam-flink"
+          files:
+          - "flink-configuration-configmap.yaml"
+          - "taskmanager-deployment.yaml"
+          - "taskmanager-service.yaml"
+          - "service-monitor.yaml"
+          - "jobmanager-service.yaml"
+          - "jobmanager-deployment.yaml"
+          #- "jobmanager-rest-service.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc1-load-generator"
+          files:
+          - "uc1-load-generator-deployment.yaml"
+          - "uc1-load-generator-service.yaml"
+  resourceTypes:
+    - typeName: "Instances"
+      patchers:
+        - type: "ReplicaPatcher"
+          resource: "taskmanager-deployment.yaml"
+        - type: "EnvVarPatcher"
+          resource: "jobmanager-deployment.yaml"
+          properties:
+            container: "jobmanager"
+            variableName: "PARALLELISM"
+        - type: "EnvVarPatcher" # required?
+          resource: "taskmanager-deployment.yaml"
+          properties:
+            container: "taskmanager"
+            variableName: "PARALLELISM"
+  loadTypes:
+    - typeName: "NumSensors"
+      patchers:
+        - type: "EnvVarPatcher"
+          resource: "uc1-load-generator-deployment.yaml"
+          properties:
+            container: "workload-generator"
+            variableName: "NUM_SENSORS"
+        - type: NumSensorsLoadGeneratorReplicaPatcher
+          resource: "uc1-load-generator-deployment.yaml"
+          properties:
+            loadGenMaxRecords: "150000"
+  kafkaConfig:
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
+    topics:
+      - name: "input"
+        numPartitions: 40
+        replicationFactor: 1
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc1-beam-samza/resources/beam-samza-service.yaml b/theodolite-benchmarks/definitions/uc1-beam-samza/resources/beam-samza-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6317caf9fe624e42449b8f630d040a068709cda3
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-beam-samza/resources/beam-samza-service.yaml
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: titan-ccp-aggregation
+  labels:
+    app: titan-ccp-aggregation
+spec:
+  #type: NodePort
+  selector:
+    app: titan-ccp-aggregation
+  ports:
+  - name: http
+    port: 80
+    targetPort: 80
+    protocol: TCP
+  - name: metrics
+    port: 5556
diff --git a/theodolite-benchmarks/definitions/uc1-beam-samza/resources/service-monitor.yaml b/theodolite-benchmarks/definitions/uc1-beam-samza/resources/service-monitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4e7e758cacb5086305efa26292ddef2afc958096
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-beam-samza/resources/service-monitor.yaml
@@ -0,0 +1,14 @@
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+  labels:
+    app: titan-ccp-aggregation
+    appScope: titan-ccp
+  name: titan-ccp-aggregation
+spec:
+  selector:
+    matchLabels:
+        app: titan-ccp-aggregation
+  endpoints:
+    - port: metrics
+      interval: 10s
diff --git a/theodolite-benchmarks/definitions/uc1-beam-samza/resources/uc1-beam-samza-deployment.yaml b/theodolite-benchmarks/definitions/uc1-beam-samza/resources/uc1-beam-samza-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..607767382b4b2fce406fe3820c0f8c6ed1cef777
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-beam-samza/resources/uc1-beam-samza-deployment.yaml
@@ -0,0 +1,60 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: titan-ccp-aggregation
+spec:
+  selector:
+    matchLabels:
+      app: titan-ccp-aggregation
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: titan-ccp-aggregation
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: uc1-beam-samza
+          image: ghcr.io/cau-se/theodolite-uc1-beam-samza:latest
+          env:
+            - name: SAMZA_JOB_COORDINATOR_ZK_CONNECT
+              value: "theodolite-kafka-zoo-entrance:2181"
+            - name: SAMZA_SYSTEMS_KAFKA_PRODUCER_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SAMZA_SYSTEMS_KAFKA_CONSUMER_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: MAX_SOURCE_PARALLELISM
+              value: "1024"
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            # - name: JAVA_OPTS
+            #   value: "-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=5555"
+            - name: COMMIT_INTERVAL_MS # Set as default for the applications
+              value: "100"
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
+      #   - name: prometheus-jmx-exporter
+      #     image: "solsson/kafka-prometheus-jmx-exporter@sha256:6f82e2b0464f50da8104acd7363fb9b995001ddff77d248379f8788e78946143"
+      #     command:
+      #       - java
+      #       - -XX:+UnlockExperimentalVMOptions
+      #       - -XX:+UseCGroupMemoryLimitForHeap
+      #       - -XX:MaxRAMFraction=1
+      #       - -XshowSettings:vm
+      #       - -jar
+      #       - jmx_prometheus_httpserver.jar
+      #       - "5556"
+      #       - /etc/jmx-aggregation/jmx-kafka-prometheus.yml
+      #     ports:
+      #       - containerPort: 5556
+      #     volumeMounts:
+      #       - name: jmx-config
+      #         mountPath: /etc/jmx-aggregation
+      # volumes:
+      #   - name: jmx-config
+      #     configMap:
+      #       name: uc1-jmx-configmap
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc1-beam-samza/uc1-beam-samza-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc1-beam-samza/uc1-beam-samza-benchmark-operator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..46030c67b135c97fcefe99482bd511f0c8138a0e
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-beam-samza/uc1-beam-samza-benchmark-operator.yaml
@@ -0,0 +1,56 @@
+apiVersion: theodolite.com/v1
+kind: benchmark
+metadata:
+  name: uc1-beam-samza
+spec:
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc1-beam-samza"
+          files:
+          - "uc1-beam-samza-deployment.yaml"
+          - "beam-samza-service.yaml"
+          - "service-monitor.yaml"
+    afterActions:
+      - selector: # delete zookeeper nodes to reset zookeeper
+          pod:
+            matchLabels:
+              app: "zookeeper-client"
+          container: "zookeeper-client"
+        exec:
+          command: ["bash", "-c", "bin/zkCli.sh -server $ZOOKEEPER_SERVER deleteall /app-theodolite-uc1-application-1"]
+          timeoutSeconds: 60
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc1-load-generator"
+          files:
+          - "uc1-load-generator-deployment.yaml"
+          - "uc1-load-generator-service.yaml"
+  resourceTypes:
+    - typeName: "Instances"
+      patchers:
+        - type: "ReplicaPatcher"
+          resource: "uc1-beam-samza-deployment.yaml"
+  loadTypes:
+    - typeName: "NumSensors"
+      patchers:
+        - type: "EnvVarPatcher"
+          resource: "uc1-load-generator-deployment.yaml"
+          properties:
+            container: "workload-generator"
+            variableName: "NUM_SENSORS"
+        - type: NumSensorsLoadGeneratorReplicaPatcher
+          resource: "uc1-load-generator-deployment.yaml"
+          properties:
+            loadGenMaxRecords: "150000"
+  kafkaConfig:
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
+    topics:
+      - name: "input"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: ".*samza.*"
+        removeOnly: true
+      - name: ".*uc1-application.*"
+        removeOnly: true
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc1-flink/resources/jobmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc1-flink/resources/jobmanager-deployment.yaml
index 1f328b1cd553c8036e570d28b97795fb2b00ec81..8e0114f17ae085057382eee597ad275c6fc0329d 100644
--- a/theodolite-benchmarks/definitions/uc1-flink/resources/jobmanager-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc1-flink/resources/jobmanager-deployment.yaml
@@ -20,7 +20,7 @@ spec:
           image: ghcr.io/cau-se/theodolite-uc1-flink:latest
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
             - name: COMMIT_INTERVAL_MS
@@ -46,7 +46,7 @@ spec:
             limits:
               memory: 4Gi
               cpu: 1000m
-          args: ["standalone-job", "--job-classname", "theodolite.uc1.application.HistoryServiceFlinkJob"] # optional arguments: ["--job-id", "<job id>", "--fromSavepoint", "/path/to/savepoint", "--allowNonRestoredState"]
+          args: ["standalone-job", "--job-classname", "rocks.theodolite.benchmarks.uc1.flink.HistoryServiceFlinkJob"] # optional arguments: ["--job-id", "<job id>", "--fromSavepoint", "/path/to/savepoint", "--allowNonRestoredState"]
           #command: ['sleep', '60m']
           ports:
             - containerPort: 6123
diff --git a/theodolite-benchmarks/definitions/uc1-flink/resources/taskmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc1-flink/resources/taskmanager-deployment.yaml
index c2266a4aeb21302262279f147e6512d5264e1dc1..9710d44cbb1ffb75e4d1ebafe1ffe60042587adc 100644
--- a/theodolite-benchmarks/definitions/uc1-flink/resources/taskmanager-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc1-flink/resources/taskmanager-deployment.yaml
@@ -20,7 +20,7 @@ spec:
           image: ghcr.io/cau-se/theodolite-uc1-flink:latest
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
             - name: COMMIT_INTERVAL_MS
diff --git a/theodolite-benchmarks/definitions/uc1-flink/uc1-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc1-flink/uc1-flink-benchmark-operator.yaml
index 89bac41ee5c8dcefa628b3cb01052df5a1df9292..20953c2d1e64895417f4f5339a0f3820d78735ac 100644
--- a/theodolite-benchmarks/definitions/uc1-flink/uc1-flink-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc1-flink/uc1-flink-benchmark-operator.yaml
@@ -50,7 +50,7 @@ spec:
           properties:
             loadGenMaxRecords: "150000"
   kafkaConfig:
-    bootstrapServer: "theodolite-cp-kafka:9092"
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
     topics:
       - name: "input"
         numPartitions: 40
diff --git a/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-hazelcastjet-deployment.yaml b/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-hazelcastjet-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..cab5a625c323628ec6d6a7152e53d3ff8393a8ba
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-hazelcastjet-deployment.yaml
@@ -0,0 +1,36 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: titan-ccp-aggregation
+spec:
+  selector:
+    matchLabels:
+      app: titan-ccp-aggregation
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: titan-ccp-aggregation
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: uc-application
+          image: uc1-hazelcastjet
+          imagePullPolicy: "Never"
+          env:
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS # Set as default for the applications
+              value: "100"
+            - name: KUBERNETES_NAMESPACE
+              valueFrom:
+                fieldRef:
+                  fieldPath: metadata.namespace
+            - name: KUBERNETES_DNS_NAME
+              value: "titan-ccp-aggregation.$(KUBERNETES_NAMESPACE).svc.cluster.local"
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-hazelcastjet-service.yaml b/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-hazelcastjet-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..845ce7dd55c6e5d45724ec1eeabf8789e704fe77
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-hazelcastjet-service.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Service
+metadata:  
+  name: titan-ccp-aggregation
+  labels:
+    app: titan-ccp-aggregation
+spec:
+  type: ClusterIP
+  clusterIP: None
+  selector:    
+    app: titan-ccp-aggregation
+  ports:  
+    - name: coordination
+      port: 5701
+      targetPort: 5701
+      protocol: TCP
diff --git a/theodolite-benchmarks/definitions/uc1-hazelcastjet/uc1-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc1-hazelcastjet/uc1-benchmark-operator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ca8994c40350ed55e2a6b927c370b3d11a6d4bfa
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-hazelcastjet/uc1-benchmark-operator.yaml
@@ -0,0 +1,42 @@
+apiVersion: theodolite.com/v1
+kind: benchmark
+metadata:
+  name: uc1-hazelcastjet
+spec:
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc1-hazelcastjet"
+          files:
+          - "uc1-hazelcastjet-deployment.yaml"
+          - "uc1-hazelcastjet-service.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc1-load-generator"
+          files:
+          - "uc1-load-generator-deployment.yaml"
+          - "uc1-load-generator-service.yaml"
+  resourceTypes:
+    - typeName: "Instances"
+      patchers:
+        - type: "ReplicaPatcher"
+          resource: "uc1-hazelcastjet-deployment.yaml"
+  loadTypes:
+    - typeName: "NumSensors"
+      patchers:
+        - type: "EnvVarPatcher"
+          resource: "uc1-load-generator-deployment.yaml"
+          properties:
+            container: "workload-generator"
+            variableName: "NUM_SENSORS"
+        - type: NumSensorsLoadGeneratorReplicaPatcher
+          resource: "uc1-load-generator-deployment.yaml"
+          properties:
+            loadGenMaxRecords: "150000"
+  kafkaConfig:
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
+    topics:
+      - name: "input"
+        numPartitions: 40
+        replicationFactor: 1
diff --git a/theodolite-benchmarks/definitions/uc1-kstreams/resources/uc1-kstreams-deployment.yaml b/theodolite-benchmarks/definitions/uc1-kstreams/resources/uc1-kstreams-deployment.yaml
index 171c3446db2719ee91bd8954233015316851fcf9..b4d2bfe738fd9c96d0219a825d5c4ef2cf5385f3 100644
--- a/theodolite-benchmarks/definitions/uc1-kstreams/resources/uc1-kstreams-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc1-kstreams/resources/uc1-kstreams-deployment.yaml
@@ -21,7 +21,7 @@ spec:
               name: jmx
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
             - name: JAVA_OPTS
diff --git a/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-operator.yaml
index fb5557c2df8b483164d3c1000717db4c7cface81..c340547c703c03a2e91738d4f53537938da97e0e 100644
--- a/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-operator.yaml
@@ -37,7 +37,7 @@ spec:
           properties:
             loadGenMaxRecords: "150000"
   kafkaConfig:
-    bootstrapServer: "theodolite-cp-kafka:9092"
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
     topics:
       - name: "input"
         numPartitions: 40
diff --git a/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-standalone.yaml b/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-standalone.yaml
index 5aaf87e724a4e8c728c3c15b998cb927ff57f3d5..545474b1c556a8185d3725c51908f996b89e91e2 100644
--- a/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-standalone.yaml
+++ b/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-standalone.yaml
@@ -32,7 +32,7 @@ loadTypes:
         properties:
           loadGenMaxRecords: "150000"
 kafkaConfig:
-  bootstrapServer: "theodolite-cp-kafka:9092"
+  bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
   topics:
     - name: "input"
       numPartitions: 40
diff --git a/theodolite-benchmarks/definitions/uc1-load-generator/resources/uc1-load-generator-deployment.yaml b/theodolite-benchmarks/definitions/uc1-load-generator/resources/uc1-load-generator-deployment.yaml
index 9f9ccc6ae39407bb1f027e1e23cb152944b869e0..65048a97d5de3d831f782db329e295a5e5ceb727 100644
--- a/theodolite-benchmarks/definitions/uc1-load-generator/resources/uc1-load-generator-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc1-load-generator/resources/uc1-load-generator-deployment.yaml
@@ -27,6 +27,6 @@ spec:
             - name: KUBERNETES_DNS_NAME
               value: "titan-ccp-load-generator.$(KUBERNETES_NAMESPACE).svc.cluster.local"
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
diff --git a/theodolite-benchmarks/definitions/uc2-beam-flink/resources/flink-configuration-configmap.yaml b/theodolite-benchmarks/definitions/uc2-beam-flink/resources/flink-configuration-configmap.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..36178e2bebdac96b8648bd6c299009aa49d3fff6
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-beam-flink/resources/flink-configuration-configmap.yaml
@@ -0,0 +1,66 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: flink-config
+  labels:
+    app: flink
+data:
+  flink-conf.yaml: |+
+    jobmanager.rpc.address: flink-jobmanager
+    taskmanager.numberOfTaskSlots: 1 #TODO
+    #blob.server.port: 6124
+    #jobmanager.rpc.port: 6123
+    #taskmanager.rpc.port: 6122
+    #queryable-state.proxy.ports: 6125
+    #jobmanager.memory.process.size: 4Gb
+    #taskmanager.memory.process.size: 4Gb
+    #parallelism.default: 1 #TODO
+    metrics.reporter.prom.class: org.apache.flink.metrics.prometheus.PrometheusReporter
+    metrics.reporter.prom.interval: 10 SECONDS
+    taskmanager.network.detailed-metrics: true
+  # -> gives metrics about inbound/outbound network queue lengths
+  log4j-console.properties: |+
+    # This affects logging for both user code and Flink
+    rootLogger.level = INFO
+    rootLogger.appenderRef.console.ref = ConsoleAppender
+    rootLogger.appenderRef.rolling.ref = RollingFileAppender
+
+    # Uncomment this if you want to _only_ change Flink's logging
+    #logger.flink.name = org.apache.flink
+    #logger.flink.level = INFO
+
+    # The following lines keep the log level of common libraries/connectors on
+    # log level INFO. The root logger does not override this. You have to manually
+    # change the log levels here.
+    logger.akka.name = akka
+    logger.akka.level = INFO
+    logger.kafka.name= org.apache.kafka
+    logger.kafka.level = INFO
+    logger.hadoop.name = org.apache.hadoop
+    logger.hadoop.level = INFO
+    logger.zookeeper.name = org.apache.zookeeper
+    logger.zookeeper.level = INFO
+
+    # Log all infos to the console
+    appender.console.name = ConsoleAppender
+    appender.console.type = CONSOLE
+    appender.console.layout.type = PatternLayout
+    appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n
+
+    # Log all infos in the given rolling file
+    appender.rolling.name = RollingFileAppender
+    appender.rolling.type = RollingFile
+    appender.rolling.append = false
+    appender.rolling.fileName = ${sys:log.file}
+    appender.rolling.filePattern = ${sys:log.file}.%i
+    appender.rolling.layout.type = PatternLayout
+    appender.rolling.layout.pattern = %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n
+    appender.rolling.policies.type = Policies
+    appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
+    appender.rolling.policies.size.size=100MB
+    appender.rolling.strategy.type = DefaultRolloverStrategy
+    appender.rolling.strategy.max = 10
+
+    # Suppress the irrelevant (wrong) warnings from the Netty channel handler
+    logger.netty.name = org.apache.flink.shaded.akka.org.jboss.netty.channel.DefaultChannelPipeline
+    logger.netty.level = OFF
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc2-beam-flink/resources/jobmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc2-beam-flink/resources/jobmanager-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..79d69aa0cfe77d80e70ff9f1d146790bce0c4577
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-beam-flink/resources/jobmanager-deployment.yaml
@@ -0,0 +1,69 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: flink-jobmanager
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: flink
+      component: jobmanager
+  template:
+    metadata:
+      labels:
+        app: flink
+        component: jobmanager
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: jobmanager
+          image: ghcr.io/cau-se/theodolite-uc2-beam-flink:latest
+          args: ["standalone-job", "--job-classname", "rocks.theodolite.benchmarks.uc2.beam.flink.Uc2BeamFlink",
+                  "--parallelism=$(PARALLELISM)",
+                  "--disableMetrics=true",
+                  "--fasterCopy"]
+          # optional arguments: ["--job-id", "<job id>", "--fromSavepoint", "/path/to/savepoint", "--allowNonRestoredState"]
+          env:
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS
+              value: "100"
+            - name: CHECKPOINTING
+              value: "false"
+            - name: PARALLELISM
+              value: "1"
+            - name: "FLINK_STATE_BACKEND"
+              value: "rocksdb"
+            - name: JOB_MANAGER_RPC_ADDRESS
+              value: "flink-jobmanager"
+            - name: FLINK_PROPERTIES
+              value: |+
+                blob.server.port: 6124
+                jobmanager.rpc.port: 6123
+                taskmanager.rpc.port: 6122
+                queryable-state.proxy.ports: 6125
+                jobmanager.memory.process.size: 4Gb
+                taskmanager.memory.process.size: 4Gb
+                parallelism.default: 1 #TODO
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
+          ports:
+            - containerPort: 6123
+              name: rpc
+            - containerPort: 6124
+              name: blob-server
+            - containerPort: 8081
+              name: webui
+            - containerPort: 9249
+              name: metrics
+          livenessProbe:
+            tcpSocket:
+              port: 6123
+            initialDelaySeconds: 30
+            periodSeconds: 60
+          securityContext:
+            runAsUser: 9999
diff --git a/theodolite-benchmarks/definitions/uc2-beam-flink/resources/jobmanager-rest-service.yaml b/theodolite-benchmarks/definitions/uc2-beam-flink/resources/jobmanager-rest-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..3d74aaf7f625c6922e2e1b4f20c19e50a39b68ac
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-beam-flink/resources/jobmanager-rest-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: flink-jobmanager-rest
+spec:
+  type: NodePort
+  ports:
+    - name: rest
+      port: 8081
+      targetPort: 8081
+      nodePort: 30081
+  selector:
+    app: flink
+    component: jobmanager
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc2-beam-flink/resources/jobmanager-service.yaml b/theodolite-benchmarks/definitions/uc2-beam-flink/resources/jobmanager-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e2ff5d9898eb1ebf5db9a827472a47514ab1473c
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-beam-flink/resources/jobmanager-service.yaml
@@ -0,0 +1,20 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: flink-jobmanager
+  labels:
+    app: flink
+spec:
+  type: ClusterIP
+  ports:
+    - name: rpc
+      port: 6123
+    - name: blob-server
+      port: 6124
+    - name: webui
+      port: 8081
+    - name: metrics
+      port: 9249
+  selector:
+    app: flink
+    component: jobmanager
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc2-beam-flink/resources/service-monitor.yaml b/theodolite-benchmarks/definitions/uc2-beam-flink/resources/service-monitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..02f78823c627e27ddfe1db5eac3f6a7f7a7f1bf8
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-beam-flink/resources/service-monitor.yaml
@@ -0,0 +1,14 @@
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+  labels:
+    app: flink
+    appScope: titan-ccp
+  name: flink
+spec:
+  selector:
+    matchLabels:
+        app: flink
+  endpoints:
+    - port: metrics
+      interval: 10s
diff --git a/theodolite-benchmarks/definitions/uc2-beam-flink/resources/taskmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc2-beam-flink/resources/taskmanager-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..86e17e96e83f991bd0b6c7bd4576d100c9222cb1
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-beam-flink/resources/taskmanager-deployment.yaml
@@ -0,0 +1,64 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: flink-taskmanager
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: flink
+      component: taskmanager
+  template:
+    metadata:
+      labels:
+        app: flink
+        component: taskmanager
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: taskmanager
+          image: ghcr.io/cau-se/theodolite-uc2-beam-flink:latest
+          args: ["taskmanager"]
+          env:
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS
+              value: "100"
+            - name: CHECKPOINTING
+              value: "false"
+            - name: "FLINK_STATE_BACKEND"
+              value: "rocksdb"
+            - name: JOB_MANAGER_RPC_ADDRESS
+              value: "flink-jobmanager"
+            # - name: TASK_MANAGER_NUMBER_OF_TASK_SLOTS
+            #   value: "1" #TODO
+            # - name: FLINK_PROPERTIES
+            #   value: |+
+            #     blob.server.port: 6124
+            #     jobmanager.rpc.port: 6123
+            #     taskmanager.rpc.port: 6122
+            #     queryable-state.proxy.ports: 6125
+            #     jobmanager.memory.process.size: 4Gb
+            #     taskmanager.memory.process.size: 4Gb
+            #     #parallelism.default: 1 #TODO
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
+          ports:
+            - containerPort: 6122
+              name: rpc
+            - containerPort: 6125
+              name: query-state
+            - containerPort: 9249
+              name: metrics
+          # livenessProbe:
+          #   tcpSocket:
+          #     port: 6122
+          #   initialDelaySeconds: 30
+          #   periodSeconds: 60
+          securityContext:
+            runAsUser: 9999  # refers to user _flink_ from official flink image, change if necessary
+
diff --git a/theodolite-benchmarks/definitions/uc2-beam-flink/resources/taskmanager-service.yaml b/theodolite-benchmarks/definitions/uc2-beam-flink/resources/taskmanager-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a2e27f64af1cfd1a26da142b8a50bb41c8ba5fcb
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-beam-flink/resources/taskmanager-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: flink-taskmanager
+  labels:
+    app: flink
+spec:
+  type: ClusterIP
+  ports:
+    - name: metrics
+      port: 9249
+  selector:
+    app: flink
+    component: taskmanager
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc2-beam-flink/uc2-beam-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc2-beam-flink/uc2-beam-flink-benchmark-operator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ffe613b401301e00cb1d368ec44609210d299df1
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-beam-flink/uc2-beam-flink-benchmark-operator.yaml
@@ -0,0 +1,62 @@
+apiVersion: theodolite.com/v1
+kind: benchmark
+metadata:
+  name: uc2-beam-flink
+spec:
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc2-beam-flink"
+          files:
+          - "flink-configuration-configmap.yaml"
+          - "taskmanager-deployment.yaml"
+          - "taskmanager-service.yaml"
+          - "service-monitor.yaml"
+          - "jobmanager-service.yaml"
+          - "jobmanager-deployment.yaml"
+          #- "jobmanager-rest-service.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc2-load-generator"
+          files:
+          - "uc2-load-generator-deployment.yaml"
+          - "uc2-load-generator-service.yaml"
+  resourceTypes:
+    - typeName: "Instances"
+      patchers:
+        - type: "ReplicaPatcher"
+          resource: "taskmanager-deployment.yaml"
+        - type: "EnvVarPatcher"
+          resource: "jobmanager-deployment.yaml"
+          properties:
+            container: "jobmanager"
+            variableName: "PARALLELISM"
+        - type: "EnvVarPatcher" # required?
+          resource: "taskmanager-deployment.yaml"
+          properties:
+            container: "taskmanager"
+            variableName: "PARALLELISM"
+  loadTypes:
+    - typeName: "NumSensors"
+      patchers:
+        - type: "EnvVarPatcher"
+          resource: "uc2-load-generator-deployment.yaml"
+          properties:
+            container: "workload-generator"
+            variableName: "NUM_SENSORS"
+        - type: NumSensorsLoadGeneratorReplicaPatcher
+          resource: "uc2-load-generator-deployment.yaml"
+          properties:
+            loadGenMaxRecords: "150000"
+  kafkaConfig:
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
+    topics:
+      - name: "input"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "output"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "theodolite-.*"
+        removeOnly: True
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc2-beam-samza/resources/beam-samza-service.yaml b/theodolite-benchmarks/definitions/uc2-beam-samza/resources/beam-samza-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6317caf9fe624e42449b8f630d040a068709cda3
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-beam-samza/resources/beam-samza-service.yaml
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: titan-ccp-aggregation
+  labels:
+    app: titan-ccp-aggregation
+spec:
+  #type: NodePort
+  selector:
+    app: titan-ccp-aggregation
+  ports:
+  - name: http
+    port: 80
+    targetPort: 80
+    protocol: TCP
+  - name: metrics
+    port: 5556
diff --git a/theodolite-benchmarks/definitions/uc2-beam-samza/resources/service-monitor.yaml b/theodolite-benchmarks/definitions/uc2-beam-samza/resources/service-monitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4e7e758cacb5086305efa26292ddef2afc958096
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-beam-samza/resources/service-monitor.yaml
@@ -0,0 +1,14 @@
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+  labels:
+    app: titan-ccp-aggregation
+    appScope: titan-ccp
+  name: titan-ccp-aggregation
+spec:
+  selector:
+    matchLabels:
+        app: titan-ccp-aggregation
+  endpoints:
+    - port: metrics
+      interval: 10s
diff --git a/theodolite-benchmarks/definitions/uc2-beam-samza/resources/uc2-beam-samza-deployment.yaml b/theodolite-benchmarks/definitions/uc2-beam-samza/resources/uc2-beam-samza-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..bcb7d82ed463a194fb0851287487a6d52cfd0198
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-beam-samza/resources/uc2-beam-samza-deployment.yaml
@@ -0,0 +1,37 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: titan-ccp-aggregation
+spec:
+  selector:
+    matchLabels:
+      app: titan-ccp-aggregation
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: titan-ccp-aggregation
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: uc2-beam-samza
+          image: ghcr.io/cau-se/theodolite-uc2-beam-samza:latest
+          env:
+            - name: SAMZA_JOB_COORDINATOR_ZK_CONNECT
+              value: "theodolite-kafka-zoo-entrance:2181"
+            - name: SAMZA_SYSTEMS_KAFKA_PRODUCER_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SAMZA_SYSTEMS_KAFKA_CONSUMER_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: MAX_SOURCE_PARALLELISM
+              value: "1024"
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS # Set as default for the applications
+              value: "100"
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc2-beam-samza/uc2-beam-samza-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc2-beam-samza/uc2-beam-samza-benchmark-operator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..46b61aaeaead664d6ed723278384c1bdf8b99ed1
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-beam-samza/uc2-beam-samza-benchmark-operator.yaml
@@ -0,0 +1,59 @@
+apiVersion: theodolite.com/v1
+kind: benchmark
+metadata:
+  name: uc2-beam-samza
+spec:
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc2-beam-samza"
+          files:
+          - "uc2-beam-samza-deployment.yaml"
+          - "beam-samza-service.yaml"
+          - "service-monitor.yaml"
+    afterActions:
+      - selector: # delete zookeeper nodes to reset zookeeper
+          pod:
+            matchLabels:
+              app: "zookeeper-client"
+          container: "zookeeper-client"
+        exec:
+          command: ["bash", "-c", "bin/zkCli.sh -server $ZOOKEEPER_SERVER deleteall /app-theodolite-uc2-application-1"]
+          timeoutSeconds: 60
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc2-load-generator"
+          files:
+          - "uc2-load-generator-deployment.yaml"
+          - "uc2-load-generator-service.yaml"
+  resourceTypes:
+    - typeName: "Instances"
+      patchers:
+        - type: "ReplicaPatcher"
+          resource: "uc2-beam-samza-deployment.yaml"
+  loadTypes:
+    - typeName: "NumSensors"
+      patchers:
+        - type: "EnvVarPatcher"
+          resource: "uc2-load-generator-deployment.yaml"
+          properties:
+            container: "workload-generator"
+            variableName: "NUM_SENSORS"
+        - type: NumSensorsLoadGeneratorReplicaPatcher
+          resource: "uc2-load-generator-deployment.yaml"
+          properties:
+            loadGenMaxRecords: "150000"
+  kafkaConfig:
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
+    topics:
+      - name: "input"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "output"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: ".*samza.*"
+        removeOnly: true
+      - name: ".*uc2-application.*"
+        removeOnly: true
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc2-flink/resources/jobmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc2-flink/resources/jobmanager-deployment.yaml
index 87ea174f71c592bbffab4e5fc9ce6e3963596b9c..f2fc1ee6a3fa01d367c52505c49bda1e58ddc134 100644
--- a/theodolite-benchmarks/definitions/uc2-flink/resources/jobmanager-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc2-flink/resources/jobmanager-deployment.yaml
@@ -20,7 +20,7 @@ spec:
           image: ghcr.io/cau-se/theodolite-uc2-flink:latest
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
             - name: COMMIT_INTERVAL_MS
@@ -46,7 +46,7 @@ spec:
             limits:
               memory: 4Gi
               cpu: 1000m
-          args: ["standalone-job", "--job-classname", "theodolite.uc2.application.HistoryServiceFlinkJob"] # optional arguments: ["--job-id", "<job id>", "--fromSavepoint", "/path/to/savepoint", "--allowNonRestoredState"]
+          args: ["standalone-job", "--job-classname", "rocks.theodolite.benchmarks.uc2.flink.HistoryServiceFlinkJob"] # optional arguments: ["--job-id", "<job id>", "--fromSavepoint", "/path/to/savepoint", "--allowNonRestoredState"]
           #command: ['sleep', '60m']
           ports:
             - containerPort: 6123
diff --git a/theodolite-benchmarks/definitions/uc2-flink/resources/taskmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc2-flink/resources/taskmanager-deployment.yaml
index c37df972a334a4a0e27f0420030f99f1dff15b53..b9a917ee825637988cf6902186d99421aac3d671 100644
--- a/theodolite-benchmarks/definitions/uc2-flink/resources/taskmanager-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc2-flink/resources/taskmanager-deployment.yaml
@@ -20,7 +20,7 @@ spec:
           image: ghcr.io/cau-se/theodolite-uc2-flink:latest
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
             - name: COMMIT_INTERVAL_MS
diff --git a/theodolite-benchmarks/definitions/uc2-flink/uc2-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc2-flink/uc2-flink-benchmark-operator.yaml
index 206fbf9683659fcc074341d7077da04c36909b75..3020bb317c8b500562f1edcf2dc770f1288a8788 100644
--- a/theodolite-benchmarks/definitions/uc2-flink/uc2-flink-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc2-flink/uc2-flink-benchmark-operator.yaml
@@ -50,7 +50,7 @@ spec:
           properties:
             loadGenMaxRecords: "150000"
   kafkaConfig:
-    bootstrapServer: "theodolite-cp-kafka:9092"
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
     topics:
       - name: "input"
         numPartitions: 40
diff --git a/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-hazelcastjet-deployment.yaml b/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-hazelcastjet-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0f5000902ddf9c12f67643cc35ffc3c882970a72
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-hazelcastjet-deployment.yaml
@@ -0,0 +1,40 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: titan-ccp-aggregation
+spec:
+  selector:
+    matchLabels:
+      app: titan-ccp-aggregation
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: titan-ccp-aggregation
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: uc-application
+          image: uc2-hazelcastjet
+          imagePullPolicy: "Never"
+          env:
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS # Set as default for the applications
+              value: "100"
+            - name: DOWNSAMPLE_INTERVAL
+              value: "5000"
+            #- name: KUBERNETES_DNS_NAME
+            #  value: "titan-ccp-aggregation"
+            - name: KUBERNETES_NAMESPACE
+              valueFrom:
+                fieldRef:
+                  fieldPath: metadata.namespace
+            - name: KUBERNETES_DNS_NAME
+              value: "titan-ccp-aggregation.$(KUBERNETES_NAMESPACE).svc.cluster.local"
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-hazelcastjet-service.yaml b/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-hazelcastjet-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..845ce7dd55c6e5d45724ec1eeabf8789e704fe77
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-hazelcastjet-service.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Service
+metadata:  
+  name: titan-ccp-aggregation
+  labels:
+    app: titan-ccp-aggregation
+spec:
+  type: ClusterIP
+  clusterIP: None
+  selector:    
+    app: titan-ccp-aggregation
+  ports:  
+    - name: coordination
+      port: 5701
+      targetPort: 5701
+      protocol: TCP
diff --git a/theodolite-benchmarks/definitions/uc2-hazelcastjet/uc2-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc2-hazelcastjet/uc2-benchmark-operator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..436bcc790c50c86e96b3b1853b198a0f6da1aec9
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-hazelcastjet/uc2-benchmark-operator.yaml
@@ -0,0 +1,47 @@
+apiVersion: theodolite.com/v1
+kind: benchmark
+metadata:
+  name: uc2-hazelcastjet
+spec:
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc2-hazelcastjet"
+          files:
+            - "uc2-hazelcastjet-deployment.yaml"
+            - "uc2-hazelcastjet-service.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc2-load-generator"
+          files:
+            - "uc2-load-generator-deployment.yaml"
+            - "uc2-load-generator-service.yaml"
+  resourceTypes:
+    - typeName: "Instances"
+      patchers:
+        - type: "ReplicaPatcher"
+          resource: "uc2-hazelcastjet-deployment.yaml"
+  loadTypes:
+    - typeName: "NumSensors"
+      patchers:
+        - type: "EnvVarPatcher"
+          resource: "uc2-load-generator-deployment.yaml"
+          properties:
+            container: "workload-generator"
+            variableName: "NUM_SENSORS"
+        - type: NumSensorsLoadGeneratorReplicaPatcher
+          resource: "uc2-load-generator-deployment.yaml"
+          properties:
+            loadGenMaxRecords: "150000"
+  kafkaConfig:
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
+    topics:
+      - name: "input"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "output"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "theodolite-.*"
+        removeOnly: True
diff --git a/theodolite-benchmarks/definitions/uc2-kstreams/resources/uc2-kstreams-deployment.yaml b/theodolite-benchmarks/definitions/uc2-kstreams/resources/uc2-kstreams-deployment.yaml
index e07bb3f9e536655712c06a004c5d1fb60ffa67e0..86932cafb26248736fbe060ba7f23ee5dded412d 100644
--- a/theodolite-benchmarks/definitions/uc2-kstreams/resources/uc2-kstreams-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc2-kstreams/resources/uc2-kstreams-deployment.yaml
@@ -21,7 +21,7 @@ spec:
               name: jmx
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
             - name: JAVA_OPTS
diff --git a/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-operator.yaml
index 0db22fa95f46d1cb484fa1a7730b8b6801dac67c..b9f2b14e369b3c8e241be62c04bd480f38d847dc 100644
--- a/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-operator.yaml
@@ -37,7 +37,7 @@ spec:
           properties:
             loadGenMaxRecords: "150000"
   kafkaConfig:
-    bootstrapServer: "theodolite-cp-kafka:9092"
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
     topics:
       - name: "input"
         numPartitions: 40
diff --git a/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-standalone.yaml b/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-standalone.yaml
index 67376d76bf0a7cc4cd47563a1d8da8dc0aa3b944..572d2b3ceac5fa43a324d4c687f72ddd1e1cdb78 100644
--- a/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-standalone.yaml
+++ b/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-standalone.yaml
@@ -33,7 +33,7 @@ loadTypes:
         properties:
           loadGenMaxRecords: "150000"
 kafkaConfig:
-  bootstrapServer: "theodolite-cp-kafka:9092"
+  bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
   topics:
     - name: "input"
       numPartitions: 40
diff --git a/theodolite-benchmarks/definitions/uc2-load-generator/resources/uc2-load-generator-deployment.yaml b/theodolite-benchmarks/definitions/uc2-load-generator/resources/uc2-load-generator-deployment.yaml
index dfc0af71543c15b12b5c850919feb0e0a4f52f28..d758c66f88fa93c98258febf6c5e6a35f7171820 100644
--- a/theodolite-benchmarks/definitions/uc2-load-generator/resources/uc2-load-generator-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc2-load-generator/resources/uc2-load-generator-deployment.yaml
@@ -27,6 +27,6 @@ spec:
             - name: KUBERNETES_DNS_NAME
               value: "titan-ccp-load-generator.$(KUBERNETES_NAMESPACE).svc.cluster.local"
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
diff --git a/theodolite-benchmarks/definitions/uc3-beam-flink/resources/flink-configuration-configmap.yaml b/theodolite-benchmarks/definitions/uc3-beam-flink/resources/flink-configuration-configmap.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..36178e2bebdac96b8648bd6c299009aa49d3fff6
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-beam-flink/resources/flink-configuration-configmap.yaml
@@ -0,0 +1,66 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: flink-config
+  labels:
+    app: flink
+data:
+  flink-conf.yaml: |+
+    jobmanager.rpc.address: flink-jobmanager
+    taskmanager.numberOfTaskSlots: 1 #TODO
+    #blob.server.port: 6124
+    #jobmanager.rpc.port: 6123
+    #taskmanager.rpc.port: 6122
+    #queryable-state.proxy.ports: 6125
+    #jobmanager.memory.process.size: 4Gb
+    #taskmanager.memory.process.size: 4Gb
+    #parallelism.default: 1 #TODO
+    metrics.reporter.prom.class: org.apache.flink.metrics.prometheus.PrometheusReporter
+    metrics.reporter.prom.interval: 10 SECONDS
+    taskmanager.network.detailed-metrics: true
+  # -> gives metrics about inbound/outbound network queue lengths
+  log4j-console.properties: |+
+    # This affects logging for both user code and Flink
+    rootLogger.level = INFO
+    rootLogger.appenderRef.console.ref = ConsoleAppender
+    rootLogger.appenderRef.rolling.ref = RollingFileAppender
+
+    # Uncomment this if you want to _only_ change Flink's logging
+    #logger.flink.name = org.apache.flink
+    #logger.flink.level = INFO
+
+    # The following lines keep the log level of common libraries/connectors on
+    # log level INFO. The root logger does not override this. You have to manually
+    # change the log levels here.
+    logger.akka.name = akka
+    logger.akka.level = INFO
+    logger.kafka.name= org.apache.kafka
+    logger.kafka.level = INFO
+    logger.hadoop.name = org.apache.hadoop
+    logger.hadoop.level = INFO
+    logger.zookeeper.name = org.apache.zookeeper
+    logger.zookeeper.level = INFO
+
+    # Log all infos to the console
+    appender.console.name = ConsoleAppender
+    appender.console.type = CONSOLE
+    appender.console.layout.type = PatternLayout
+    appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n
+
+    # Log all infos in the given rolling file
+    appender.rolling.name = RollingFileAppender
+    appender.rolling.type = RollingFile
+    appender.rolling.append = false
+    appender.rolling.fileName = ${sys:log.file}
+    appender.rolling.filePattern = ${sys:log.file}.%i
+    appender.rolling.layout.type = PatternLayout
+    appender.rolling.layout.pattern = %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n
+    appender.rolling.policies.type = Policies
+    appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
+    appender.rolling.policies.size.size=100MB
+    appender.rolling.strategy.type = DefaultRolloverStrategy
+    appender.rolling.strategy.max = 10
+
+    # Suppress the irrelevant (wrong) warnings from the Netty channel handler
+    logger.netty.name = org.apache.flink.shaded.akka.org.jboss.netty.channel.DefaultChannelPipeline
+    logger.netty.level = OFF
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc3-beam-flink/resources/jobmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc3-beam-flink/resources/jobmanager-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c44f32f0846de4b32afeba2344abcd6f805c38b2
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-beam-flink/resources/jobmanager-deployment.yaml
@@ -0,0 +1,69 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: flink-jobmanager
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: flink
+      component: jobmanager
+  template:
+    metadata:
+      labels:
+        app: flink
+        component: jobmanager
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: jobmanager
+          image: ghcr.io/cau-se/theodolite-uc3-beam-flink:latest
+          args: ["standalone-job", "--job-classname", "rocks.theodolite.benchmarks.uc3.beam.flink.Uc3BeamFlink",
+                  "--parallelism=$(PARALLELISM)",
+                  "--disableMetrics=true",
+                  "--fasterCopy"]
+          # optional arguments: ["--job-id", "<job id>", "--fromSavepoint", "/path/to/savepoint", "--allowNonRestoredState"]
+          env:
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS
+              value: "100"
+            - name: CHECKPOINTING
+              value: "false"
+            - name: PARALLELISM
+              value: "1"
+            - name: "FLINK_STATE_BACKEND"
+              value: "rocksdb"
+            - name: JOB_MANAGER_RPC_ADDRESS
+              value: "flink-jobmanager"
+            - name: FLINK_PROPERTIES
+              value: |+
+                blob.server.port: 6124
+                jobmanager.rpc.port: 6123
+                taskmanager.rpc.port: 6122
+                queryable-state.proxy.ports: 6125
+                jobmanager.memory.process.size: 4Gb
+                taskmanager.memory.process.size: 4Gb
+                parallelism.default: 1 #TODO
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
+          ports:
+            - containerPort: 6123
+              name: rpc
+            - containerPort: 6124
+              name: blob-server
+            - containerPort: 8081
+              name: webui
+            - containerPort: 9249
+              name: metrics
+          livenessProbe:
+            tcpSocket:
+              port: 6123
+            initialDelaySeconds: 30
+            periodSeconds: 60
+          securityContext:
+            runAsUser: 9999
diff --git a/theodolite-benchmarks/definitions/uc3-beam-flink/resources/jobmanager-rest-service.yaml b/theodolite-benchmarks/definitions/uc3-beam-flink/resources/jobmanager-rest-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..3d74aaf7f625c6922e2e1b4f20c19e50a39b68ac
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-beam-flink/resources/jobmanager-rest-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: flink-jobmanager-rest
+spec:
+  type: NodePort
+  ports:
+    - name: rest
+      port: 8081
+      targetPort: 8081
+      nodePort: 30081
+  selector:
+    app: flink
+    component: jobmanager
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc3-beam-flink/resources/jobmanager-service.yaml b/theodolite-benchmarks/definitions/uc3-beam-flink/resources/jobmanager-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e2ff5d9898eb1ebf5db9a827472a47514ab1473c
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-beam-flink/resources/jobmanager-service.yaml
@@ -0,0 +1,20 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: flink-jobmanager
+  labels:
+    app: flink
+spec:
+  type: ClusterIP
+  ports:
+    - name: rpc
+      port: 6123
+    - name: blob-server
+      port: 6124
+    - name: webui
+      port: 8081
+    - name: metrics
+      port: 9249
+  selector:
+    app: flink
+    component: jobmanager
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc3-beam-flink/resources/service-monitor.yaml b/theodolite-benchmarks/definitions/uc3-beam-flink/resources/service-monitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..02f78823c627e27ddfe1db5eac3f6a7f7a7f1bf8
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-beam-flink/resources/service-monitor.yaml
@@ -0,0 +1,14 @@
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+  labels:
+    app: flink
+    appScope: titan-ccp
+  name: flink
+spec:
+  selector:
+    matchLabels:
+        app: flink
+  endpoints:
+    - port: metrics
+      interval: 10s
diff --git a/theodolite-benchmarks/definitions/uc3-beam-flink/resources/taskmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc3-beam-flink/resources/taskmanager-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a0a840fad96fa21212bb25c78a597ea5cb41558c
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-beam-flink/resources/taskmanager-deployment.yaml
@@ -0,0 +1,64 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: flink-taskmanager
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: flink
+      component: taskmanager
+  template:
+    metadata:
+      labels:
+        app: flink
+        component: taskmanager
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: taskmanager
+          image: ghcr.io/cau-se/theodolite-uc3-beam-flink:latest
+          args: ["taskmanager"]
+          env:
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS
+              value: "100"
+            - name: CHECKPOINTING
+              value: "false"
+            - name: "FLINK_STATE_BACKEND"
+              value: "rocksdb"
+            - name: JOB_MANAGER_RPC_ADDRESS
+              value: "flink-jobmanager"
+            # - name: TASK_MANAGER_NUMBER_OF_TASK_SLOTS
+            #   value: "1" #TODO
+            # - name: FLINK_PROPERTIES
+            #   value: |+
+            #     blob.server.port: 6124
+            #     jobmanager.rpc.port: 6123
+            #     taskmanager.rpc.port: 6122
+            #     queryable-state.proxy.ports: 6125
+            #     jobmanager.memory.process.size: 4Gb
+            #     taskmanager.memory.process.size: 4Gb
+            #     #parallelism.default: 1 #TODO
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
+          ports:
+            - containerPort: 6122
+              name: rpc
+            - containerPort: 6125
+              name: query-state
+            - containerPort: 9249
+              name: metrics
+          # livenessProbe:
+          #   tcpSocket:
+          #     port: 6122
+          #   initialDelaySeconds: 30
+          #   periodSeconds: 60
+          securityContext:
+            runAsUser: 9999  # refers to user _flink_ from official flink image, change if necessary
+
diff --git a/theodolite-benchmarks/definitions/uc3-beam-flink/resources/taskmanager-service.yaml b/theodolite-benchmarks/definitions/uc3-beam-flink/resources/taskmanager-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a2e27f64af1cfd1a26da142b8a50bb41c8ba5fcb
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-beam-flink/resources/taskmanager-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: flink-taskmanager
+  labels:
+    app: flink
+spec:
+  type: ClusterIP
+  ports:
+    - name: metrics
+      port: 9249
+  selector:
+    app: flink
+    component: taskmanager
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc3-beam-flink/uc3-beam-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc3-beam-flink/uc3-beam-flink-benchmark-operator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4449252c0de5aa81c3069b65c19325256bab57e9
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-beam-flink/uc3-beam-flink-benchmark-operator.yaml
@@ -0,0 +1,62 @@
+apiVersion: theodolite.com/v1
+kind: benchmark
+metadata:
+  name: uc3-beam-flink
+spec:
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc3-beam-flink"
+          files:
+          - "flink-configuration-configmap.yaml"
+          - "taskmanager-deployment.yaml"
+          - "taskmanager-service.yaml"
+          - "service-monitor.yaml"
+          - "jobmanager-service.yaml"
+          - "jobmanager-deployment.yaml"
+          #- "jobmanager-rest-service.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc3-load-generator"
+          files:
+          - "uc3-load-generator-deployment.yaml"
+          - "uc3-load-generator-service.yaml"
+  resourceTypes:
+    - typeName: "Instances"
+      patchers:
+        - type: "ReplicaPatcher"
+          resource: "taskmanager-deployment.yaml"
+        - type: "EnvVarPatcher"
+          resource: "jobmanager-deployment.yaml"
+          properties:
+            container: "jobmanager"
+            variableName: "PARALLELISM"
+        - type: "EnvVarPatcher" # required?
+          resource: "taskmanager-deployment.yaml"
+          properties:
+            container: "taskmanager"
+            variableName: "PARALLELISM"
+  loadTypes:
+    - typeName: "NumSensors"
+      patchers:
+        - type: "EnvVarPatcher"
+          resource: "uc3-load-generator-deployment.yaml"
+          properties:
+            container: "workload-generator"
+            variableName: "NUM_SENSORS"
+        - type: NumSensorsLoadGeneratorReplicaPatcher
+          resource: "uc3-load-generator-deployment.yaml"
+          properties:
+            loadGenMaxRecords: "150000"
+  kafkaConfig:
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
+    topics:
+      - name: "input"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "output"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "theodolite-.*"
+        removeOnly: True
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc3-beam-samza/resources/beam-samza-service.yaml b/theodolite-benchmarks/definitions/uc3-beam-samza/resources/beam-samza-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6317caf9fe624e42449b8f630d040a068709cda3
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-beam-samza/resources/beam-samza-service.yaml
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: titan-ccp-aggregation
+  labels:
+    app: titan-ccp-aggregation
+spec:
+  #type: NodePort
+  selector:
+    app: titan-ccp-aggregation
+  ports:
+  - name: http
+    port: 80
+    targetPort: 80
+    protocol: TCP
+  - name: metrics
+    port: 5556
diff --git a/theodolite-benchmarks/definitions/uc3-beam-samza/resources/service-monitor.yaml b/theodolite-benchmarks/definitions/uc3-beam-samza/resources/service-monitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4e7e758cacb5086305efa26292ddef2afc958096
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-beam-samza/resources/service-monitor.yaml
@@ -0,0 +1,14 @@
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+  labels:
+    app: titan-ccp-aggregation
+    appScope: titan-ccp
+  name: titan-ccp-aggregation
+spec:
+  selector:
+    matchLabels:
+        app: titan-ccp-aggregation
+  endpoints:
+    - port: metrics
+      interval: 10s
diff --git a/theodolite-benchmarks/definitions/uc3-beam-samza/resources/uc3-beam-samza-deployment.yaml b/theodolite-benchmarks/definitions/uc3-beam-samza/resources/uc3-beam-samza-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..aff9da6a0f7ee490a94a6f9954c2b3cc8a2b5ed5
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-beam-samza/resources/uc3-beam-samza-deployment.yaml
@@ -0,0 +1,37 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: titan-ccp-aggregation
+spec:
+  selector:
+    matchLabels:
+      app: titan-ccp-aggregation
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: titan-ccp-aggregation
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: uc3-beam-samza
+          image: ghcr.io/cau-se/theodolite-uc3-beam-samza:latest
+          env:
+            - name: SAMZA_JOB_COORDINATOR_ZK_CONNECT
+              value: "theodolite-kafka-zoo-entrance:2181"
+            - name: SAMZA_SYSTEMS_KAFKA_PRODUCER_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SAMZA_SYSTEMS_KAFKA_CONSUMER_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: MAX_SOURCE_PARALLELISM
+              value: "1024"
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS # Set as default for the applications
+              value: "100"
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc3-beam-samza/uc3-beam-samza-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc3-beam-samza/uc3-beam-samza-benchmark-operator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..36d812d4ca1fd226c7edcd96472b5aefff26bfda
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-beam-samza/uc3-beam-samza-benchmark-operator.yaml
@@ -0,0 +1,59 @@
+apiVersion: theodolite.com/v1
+kind: benchmark
+metadata:
+  name: uc3-beam-samza
+spec:
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc3-beam-samza"
+          files:
+          - "uc3-beam-samza-deployment.yaml"
+          - "beam-samza-service.yaml"
+          - "service-monitor.yaml"
+    afterActions:
+      - selector: # delete zookeeper nodes to reset zookeeper
+          pod:
+            matchLabels:
+              app: "zookeeper-client"
+          container: "zookeeper-client"
+        exec:
+          command: ["bash", "-c", "bin/zkCli.sh -server $ZOOKEEPER_SERVER deleteall /app-theodolite-uc3-application-1"]
+          timeoutSeconds: 60
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc3-load-generator"
+          files:
+          - "uc3-load-generator-deployment.yaml"
+          - "uc3-load-generator-service.yaml"
+  resourceTypes:
+    - typeName: "Instances"
+      patchers:
+        - type: "ReplicaPatcher"
+          resource: "uc3-beam-samza-deployment.yaml"
+  loadTypes:
+    - typeName: "NumSensors"
+      patchers:
+        - type: "EnvVarPatcher"
+          resource: "uc3-load-generator-deployment.yaml"
+          properties:
+            container: "workload-generator"
+            variableName: "NUM_SENSORS"
+        - type: NumSensorsLoadGeneratorReplicaPatcher
+          resource: "uc3-load-generator-deployment.yaml"
+          properties:
+            loadGenMaxRecords: "150000"
+  kafkaConfig:
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
+    topics:
+      - name: "input"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "output"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: ".*samza.*"
+        removeOnly: true
+      - name: ".*uc3-application.*"
+        removeOnly: true
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc3-flink/resources/jobmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc3-flink/resources/jobmanager-deployment.yaml
index d01123b13fe2d63637ee4000051091a99bad0546..f1c56b3a51ec884dca25a31ffafea195919a02e2 100644
--- a/theodolite-benchmarks/definitions/uc3-flink/resources/jobmanager-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc3-flink/resources/jobmanager-deployment.yaml
@@ -20,7 +20,7 @@ spec:
           image: ghcr.io/cau-se/theodolite-uc3-flink:latest
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
             - name: COMMIT_INTERVAL_MS
@@ -46,7 +46,7 @@ spec:
             limits:
               memory: 4Gi
               cpu: 1000m
-          args: ["standalone-job", "--job-classname", "theodolite.uc3.application.HistoryServiceFlinkJob"] # optional arguments: ["--job-id", "<job id>", "--fromSavepoint", "/path/to/savepoint", "--allowNonRestoredState"]
+          args: ["standalone-job", "--job-classname", "rocks.theodolite.benchmarks.uc3.flink.HistoryServiceFlinkJob"] # optional arguments: ["--job-id", "<job id>", "--fromSavepoint", "/path/to/savepoint", "--allowNonRestoredState"]
           #command: ['sleep', '60m']
           ports:
             - containerPort: 6123
diff --git a/theodolite-benchmarks/definitions/uc3-flink/resources/taskmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc3-flink/resources/taskmanager-deployment.yaml
index 495f97817e43d692c30fe898c4ef3118cae682d7..cc1efa23c32220c7c664d8aaa4669f3af6492d15 100644
--- a/theodolite-benchmarks/definitions/uc3-flink/resources/taskmanager-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc3-flink/resources/taskmanager-deployment.yaml
@@ -20,7 +20,7 @@ spec:
           image: ghcr.io/cau-se/theodolite-uc3-flink:latest
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
             - name: COMMIT_INTERVAL_MS
diff --git a/theodolite-benchmarks/definitions/uc3-flink/uc3-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc3-flink/uc3-flink-benchmark-operator.yaml
index 47b64d9890fc0f300ee1bd8e67acbdf7c8c4e4f9..0b6e2490f3b58e5c843f2719b24378b46406c6a9 100644
--- a/theodolite-benchmarks/definitions/uc3-flink/uc3-flink-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc3-flink/uc3-flink-benchmark-operator.yaml
@@ -50,7 +50,7 @@ spec:
           properties:
             loadGenMaxRecords: "150000"
   kafkaConfig:
-    bootstrapServer: "theodolite-cp-kafka:9092"
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
     topics:
       - name: "input"
         numPartitions: 40
diff --git a/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-hazelcastjet-deployment.yaml b/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-hazelcastjet-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..317d30328ec9ba3c0c30bf87733b3801e73d2477
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-hazelcastjet-deployment.yaml
@@ -0,0 +1,42 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: titan-ccp-aggregation
+spec:
+  selector:
+    matchLabels:
+      app: titan-ccp-aggregation
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: titan-ccp-aggregation
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: uc-application
+          image: uc3-hazelcastjet
+          imagePullPolicy: "Never"
+          env:
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS # Set as default for the applications
+              value: "100"
+            - name: WINDOW_SIZE_IN_SECONDS
+              value: "50"
+            - name: HOPPING_SIZE_IN_SECONDS
+              value: "1"
+            #- name: KUBERNETES_DNS_NAME
+            #  value: "titan-ccp-aggregation"
+            - name: KUBERNETES_NAMESPACE
+              valueFrom:
+                fieldRef:
+                  fieldPath: metadata.namespace
+            - name: KUBERNETES_DNS_NAME
+              value: "titan-ccp-aggregation.$(KUBERNETES_NAMESPACE).svc.cluster.local"
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-hazelcastjet-service.yaml b/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-hazelcastjet-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..845ce7dd55c6e5d45724ec1eeabf8789e704fe77
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-hazelcastjet-service.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Service
+metadata:  
+  name: titan-ccp-aggregation
+  labels:
+    app: titan-ccp-aggregation
+spec:
+  type: ClusterIP
+  clusterIP: None
+  selector:    
+    app: titan-ccp-aggregation
+  ports:  
+    - name: coordination
+      port: 5701
+      targetPort: 5701
+      protocol: TCP
diff --git a/theodolite-benchmarks/definitions/uc3-hazelcastjet/uc3-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc3-hazelcastjet/uc3-benchmark-operator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..3d9f755dc741458b0c8a27fe5ef450b09478b8cb
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-hazelcastjet/uc3-benchmark-operator.yaml
@@ -0,0 +1,47 @@
+apiVersion: theodolite.com/v1
+kind: benchmark
+metadata:
+  name: uc3-hazelcastjet
+spec:
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc3-hazelcastjet"
+          files:
+            - "uc3-hazelcastjet-deployment.yaml"
+            - "uc3-hazelcastjet-service.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc3-load-generator"
+          files:
+            - "uc3-load-generator-deployment.yaml"
+            - "uc3-load-generator-service.yaml"
+  resourceTypes:
+    - typeName: "Instances"
+      patchers:
+        - type: "ReplicaPatcher"
+          resource: "uc3-hazelcastjet-deployment.yaml"
+  loadTypes:
+    - typeName: "NumSensors"
+      patchers:
+        - type: "EnvVarPatcher"
+          resource: "uc3-load-generator-deployment.yaml"
+          properties:
+            container: "workload-generator"
+            variableName: "NUM_SENSORS"
+        - type: NumSensorsLoadGeneratorReplicaPatcher
+          resource: "uc3-load-generator-deployment.yaml"
+          properties:
+            loadGenMaxRecords: "150000"
+  kafkaConfig:
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
+    topics:
+      - name: "input"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "output"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "theodolite-.*"
+        removeOnly: True
diff --git a/theodolite-benchmarks/definitions/uc3-kstreams/resources/uc3-kstreams-deployment.yaml b/theodolite-benchmarks/definitions/uc3-kstreams/resources/uc3-kstreams-deployment.yaml
index e3f63fae9e245e6116e0fe451480d9bc74b36433..0b58c15fd123c9d06e441084063eae40d20cc48a 100644
--- a/theodolite-benchmarks/definitions/uc3-kstreams/resources/uc3-kstreams-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc3-kstreams/resources/uc3-kstreams-deployment.yaml
@@ -21,7 +21,7 @@ spec:
               name: jmx
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
             - name: JAVA_OPTS
diff --git a/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-operator.yaml
index 25374ad92a32782857cea5924ea6482060832eac..1db619303fe1bb108205654c2245b8032b723c15 100644
--- a/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-operator.yaml
@@ -37,7 +37,7 @@ spec:
           properties:
             loadGenMaxRecords: "150000"
   kafkaConfig:
-    bootstrapServer: "theodolite-cp-kafka:9092"
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
     topics:
       - name: "input"
         numPartitions: 40
diff --git a/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-standalone.yaml b/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-standalone.yaml
index aa92913d2c992835078174747ea849ce296c3eb1..f879e0949e325e2e2cd830231170775935bda65d 100644
--- a/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-standalone.yaml
+++ b/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-standalone.yaml
@@ -33,7 +33,7 @@ loadTypes:
         properties:
           loadGenMaxRecords: "150000"
 kafkaConfig:
-  bootstrapServer: "theodolite-cp-kafka:9092"
+  bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
   topics:
     - name: "input"
       numPartitions: 40
diff --git a/theodolite-benchmarks/definitions/uc3-load-generator/resources/uc3-load-generator-deployment.yaml b/theodolite-benchmarks/definitions/uc3-load-generator/resources/uc3-load-generator-deployment.yaml
index c1cad0b70fd82a5bbb43792ee79f9cf5cc71d95f..928e0a91b210e786b3d6b156e964a7fb9a7cc184 100644
--- a/theodolite-benchmarks/definitions/uc3-load-generator/resources/uc3-load-generator-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc3-load-generator/resources/uc3-load-generator-deployment.yaml
@@ -27,6 +27,6 @@ spec:
             - name: KUBERNETES_DNS_NAME
               value: "titan-ccp-load-generator.$(KUBERNETES_NAMESPACE).svc.cluster.local"
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
diff --git a/theodolite-benchmarks/definitions/uc4-beam-flink/resources/flink-configuration-configmap.yaml b/theodolite-benchmarks/definitions/uc4-beam-flink/resources/flink-configuration-configmap.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..36178e2bebdac96b8648bd6c299009aa49d3fff6
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-beam-flink/resources/flink-configuration-configmap.yaml
@@ -0,0 +1,66 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: flink-config
+  labels:
+    app: flink
+data:
+  flink-conf.yaml: |+
+    jobmanager.rpc.address: flink-jobmanager
+    taskmanager.numberOfTaskSlots: 1 #TODO
+    #blob.server.port: 6124
+    #jobmanager.rpc.port: 6123
+    #taskmanager.rpc.port: 6122
+    #queryable-state.proxy.ports: 6125
+    #jobmanager.memory.process.size: 4Gb
+    #taskmanager.memory.process.size: 4Gb
+    #parallelism.default: 1 #TODO
+    metrics.reporter.prom.class: org.apache.flink.metrics.prometheus.PrometheusReporter
+    metrics.reporter.prom.interval: 10 SECONDS
+    taskmanager.network.detailed-metrics: true
+  # -> gives metrics about inbound/outbound network queue lengths
+  log4j-console.properties: |+
+    # This affects logging for both user code and Flink
+    rootLogger.level = INFO
+    rootLogger.appenderRef.console.ref = ConsoleAppender
+    rootLogger.appenderRef.rolling.ref = RollingFileAppender
+
+    # Uncomment this if you want to _only_ change Flink's logging
+    #logger.flink.name = org.apache.flink
+    #logger.flink.level = INFO
+
+    # The following lines keep the log level of common libraries/connectors on
+    # log level INFO. The root logger does not override this. You have to manually
+    # change the log levels here.
+    logger.akka.name = akka
+    logger.akka.level = INFO
+    logger.kafka.name= org.apache.kafka
+    logger.kafka.level = INFO
+    logger.hadoop.name = org.apache.hadoop
+    logger.hadoop.level = INFO
+    logger.zookeeper.name = org.apache.zookeeper
+    logger.zookeeper.level = INFO
+
+    # Log all infos to the console
+    appender.console.name = ConsoleAppender
+    appender.console.type = CONSOLE
+    appender.console.layout.type = PatternLayout
+    appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n
+
+    # Log all infos in the given rolling file
+    appender.rolling.name = RollingFileAppender
+    appender.rolling.type = RollingFile
+    appender.rolling.append = false
+    appender.rolling.fileName = ${sys:log.file}
+    appender.rolling.filePattern = ${sys:log.file}.%i
+    appender.rolling.layout.type = PatternLayout
+    appender.rolling.layout.pattern = %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n
+    appender.rolling.policies.type = Policies
+    appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
+    appender.rolling.policies.size.size=100MB
+    appender.rolling.strategy.type = DefaultRolloverStrategy
+    appender.rolling.strategy.max = 10
+
+    # Suppress the irrelevant (wrong) warnings from the Netty channel handler
+    logger.netty.name = org.apache.flink.shaded.akka.org.jboss.netty.channel.DefaultChannelPipeline
+    logger.netty.level = OFF
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc4-beam-flink/resources/jobmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc4-beam-flink/resources/jobmanager-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..fb54893cc8dcea45fd6c657d25eb97b40399a29e
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-beam-flink/resources/jobmanager-deployment.yaml
@@ -0,0 +1,69 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: flink-jobmanager
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: flink
+      component: jobmanager
+  template:
+    metadata:
+      labels:
+        app: flink
+        component: jobmanager
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: jobmanager
+          image: ghcr.io/cau-se/theodolite-uc4-beam-flink:latest
+          args: ["standalone-job", "--job-classname", "rocks.theodolite.benchmarks.uc4.beam.flink.Uc4BeamFlink",
+                  "--parallelism=$(PARALLELISM)",
+                  "--disableMetrics=true",
+                  "--fasterCopy"]
+          # optional arguments: ["--job-id", "<job id>", "--fromSavepoint", "/path/to/savepoint", "--allowNonRestoredState"]
+          env:
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS
+              value: "100"
+            - name: CHECKPOINTING
+              value: "false"
+            - name: PARALLELISM
+              value: "1"
+            - name: "FLINK_STATE_BACKEND"
+              value: "rocksdb"
+            - name: JOB_MANAGER_RPC_ADDRESS
+              value: "flink-jobmanager"
+            - name: FLINK_PROPERTIES
+              value: |+
+                blob.server.port: 6124
+                jobmanager.rpc.port: 6123
+                taskmanager.rpc.port: 6122
+                queryable-state.proxy.ports: 6125
+                jobmanager.memory.process.size: 4Gb
+                taskmanager.memory.process.size: 4Gb
+                parallelism.default: 1 #TODO
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
+          ports:
+            - containerPort: 6123
+              name: rpc
+            - containerPort: 6124
+              name: blob-server
+            - containerPort: 8081
+              name: webui
+            - containerPort: 9249
+              name: metrics
+          livenessProbe:
+            tcpSocket:
+              port: 6123
+            initialDelaySeconds: 30
+            periodSeconds: 60
+          securityContext:
+            runAsUser: 9999
diff --git a/theodolite-benchmarks/definitions/uc4-beam-flink/resources/jobmanager-rest-service.yaml b/theodolite-benchmarks/definitions/uc4-beam-flink/resources/jobmanager-rest-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..3d74aaf7f625c6922e2e1b4f20c19e50a39b68ac
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-beam-flink/resources/jobmanager-rest-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: flink-jobmanager-rest
+spec:
+  type: NodePort
+  ports:
+    - name: rest
+      port: 8081
+      targetPort: 8081
+      nodePort: 30081
+  selector:
+    app: flink
+    component: jobmanager
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc4-beam-flink/resources/jobmanager-service.yaml b/theodolite-benchmarks/definitions/uc4-beam-flink/resources/jobmanager-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e2ff5d9898eb1ebf5db9a827472a47514ab1473c
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-beam-flink/resources/jobmanager-service.yaml
@@ -0,0 +1,20 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: flink-jobmanager
+  labels:
+    app: flink
+spec:
+  type: ClusterIP
+  ports:
+    - name: rpc
+      port: 6123
+    - name: blob-server
+      port: 6124
+    - name: webui
+      port: 8081
+    - name: metrics
+      port: 9249
+  selector:
+    app: flink
+    component: jobmanager
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc4-beam-flink/resources/service-monitor.yaml b/theodolite-benchmarks/definitions/uc4-beam-flink/resources/service-monitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..02f78823c627e27ddfe1db5eac3f6a7f7a7f1bf8
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-beam-flink/resources/service-monitor.yaml
@@ -0,0 +1,14 @@
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+  labels:
+    app: flink
+    appScope: titan-ccp
+  name: flink
+spec:
+  selector:
+    matchLabels:
+        app: flink
+  endpoints:
+    - port: metrics
+      interval: 10s
diff --git a/theodolite-benchmarks/definitions/uc4-beam-flink/resources/taskmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc4-beam-flink/resources/taskmanager-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5eabd7d52875b8ea556a4b47fde18cf859a279b7
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-beam-flink/resources/taskmanager-deployment.yaml
@@ -0,0 +1,64 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: flink-taskmanager
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: flink
+      component: taskmanager
+  template:
+    metadata:
+      labels:
+        app: flink
+        component: taskmanager
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: taskmanager
+          image: ghcr.io/cau-se/theodolite-uc4-beam-flink:latest
+          args: ["taskmanager"]
+          env:
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS
+              value: "100"
+            - name: CHECKPOINTING
+              value: "false"
+            - name: "FLINK_STATE_BACKEND"
+              value: "rocksdb"
+            - name: JOB_MANAGER_RPC_ADDRESS
+              value: "flink-jobmanager"
+            # - name: TASK_MANAGER_NUMBER_OF_TASK_SLOTS
+            #   value: "1" #TODO
+            # - name: FLINK_PROPERTIES
+            #   value: |+
+            #     blob.server.port: 6124
+            #     jobmanager.rpc.port: 6123
+            #     taskmanager.rpc.port: 6122
+            #     queryable-state.proxy.ports: 6125
+            #     jobmanager.memory.process.size: 4Gb
+            #     taskmanager.memory.process.size: 4Gb
+            #     #parallelism.default: 1 #TODO
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
+          ports:
+            - containerPort: 6122
+              name: rpc
+            - containerPort: 6125
+              name: query-state
+            - containerPort: 9249
+              name: metrics
+          # livenessProbe:
+          #   tcpSocket:
+          #     port: 6122
+          #   initialDelaySeconds: 30
+          #   periodSeconds: 60
+          securityContext:
+            runAsUser: 9999  # refers to user _flink_ from official flink image, change if necessary
+
diff --git a/theodolite-benchmarks/definitions/uc4-beam-flink/resources/taskmanager-service.yaml b/theodolite-benchmarks/definitions/uc4-beam-flink/resources/taskmanager-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a2e27f64af1cfd1a26da142b8a50bb41c8ba5fcb
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-beam-flink/resources/taskmanager-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: flink-taskmanager
+  labels:
+    app: flink
+spec:
+  type: ClusterIP
+  ports:
+    - name: metrics
+      port: 9249
+  selector:
+    app: flink
+    component: taskmanager
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc4-beam-flink/uc4-beam-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc4-beam-flink/uc4-beam-flink-benchmark-operator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..738b1c837469a9272bf27d4df08d6e5242b1a4c2
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-beam-flink/uc4-beam-flink-benchmark-operator.yaml
@@ -0,0 +1,69 @@
+apiVersion: theodolite.com/v1
+kind: benchmark
+metadata:
+  name: uc4-beam-flink
+spec:
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc4-beam-flink"
+          files:
+          - "flink-configuration-configmap.yaml"
+          - "taskmanager-deployment.yaml"
+          - "taskmanager-service.yaml"
+          - "service-monitor.yaml"
+          - "jobmanager-service.yaml"
+          - "jobmanager-deployment.yaml"
+          #- "jobmanager-rest-service.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc4-load-generator"
+          files:
+          - "uc4-load-generator-deployment.yaml"
+          - "uc4-load-generator-service.yaml"
+  resourceTypes:
+    - typeName: "Instances"
+      patchers:
+        - type: "ReplicaPatcher"
+          resource: "taskmanager-deployment.yaml"
+        - type: "EnvVarPatcher"
+          resource: "jobmanager-deployment.yaml"
+          properties:
+            container: "jobmanager"
+            variableName: "PARALLELISM"
+        - type: "EnvVarPatcher" # required?
+          resource: "taskmanager-deployment.yaml"
+          properties:
+            container: "taskmanager"
+            variableName: "PARALLELISM"
+  loadTypes:
+    - typeName: "NumNestedGroups"
+      patchers:
+        - type: "EnvVarPatcher"
+          resource: "uc4-load-generator-deployment.yaml"
+          properties:
+            container: "workload-generator"
+            variableName: "NUM_NESTED_GROUPS"
+        - type: NumNestedGroupsLoadGeneratorReplicaPatcher
+          resource: "uc4-load-generator-deployment.yaml"
+          properties:
+            loadGenMaxRecords: "150000"
+            numSensors: "4.0"
+  kafkaConfig:
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
+    topics:
+      - name: "input"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "output"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "configuration"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "aggregation-feedback"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "theodolite-.*"
+        removeOnly: True
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc4-beam-samza/resources/beam-samza-service.yaml b/theodolite-benchmarks/definitions/uc4-beam-samza/resources/beam-samza-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6317caf9fe624e42449b8f630d040a068709cda3
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-beam-samza/resources/beam-samza-service.yaml
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: titan-ccp-aggregation
+  labels:
+    app: titan-ccp-aggregation
+spec:
+  #type: NodePort
+  selector:
+    app: titan-ccp-aggregation
+  ports:
+  - name: http
+    port: 80
+    targetPort: 80
+    protocol: TCP
+  - name: metrics
+    port: 5556
diff --git a/theodolite-benchmarks/definitions/uc4-beam-samza/resources/service-monitor.yaml b/theodolite-benchmarks/definitions/uc4-beam-samza/resources/service-monitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4e7e758cacb5086305efa26292ddef2afc958096
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-beam-samza/resources/service-monitor.yaml
@@ -0,0 +1,14 @@
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+  labels:
+    app: titan-ccp-aggregation
+    appScope: titan-ccp
+  name: titan-ccp-aggregation
+spec:
+  selector:
+    matchLabels:
+        app: titan-ccp-aggregation
+  endpoints:
+    - port: metrics
+      interval: 10s
diff --git a/theodolite-benchmarks/definitions/uc4-beam-samza/resources/uc4-beam-samza-deployment.yaml b/theodolite-benchmarks/definitions/uc4-beam-samza/resources/uc4-beam-samza-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c0602d86207d2e63d3eb549b068b0afe2692df21
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-beam-samza/resources/uc4-beam-samza-deployment.yaml
@@ -0,0 +1,37 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: titan-ccp-aggregation
+spec:
+  selector:
+    matchLabels:
+      app: titan-ccp-aggregation
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: titan-ccp-aggregation
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: uc4-beam-samza
+          image: ghcr.io/cau-se/theodolite-uc4-beam-samza:latest
+          env:
+            - name: SAMZA_JOB_COORDINATOR_ZK_CONNECT
+              value: "theodolite-kafka-zoo-entrance:2181"
+            - name: SAMZA_SYSTEMS_KAFKA_PRODUCER_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SAMZA_SYSTEMS_KAFKA_CONSUMER_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: MAX_SOURCE_PARALLELISM
+              value: "1024"
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS # Set as default for the applications
+              value: "100"
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc4-beam-samza/uc4-beam-samza-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc4-beam-samza/uc4-beam-samza-benchmark-operator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..12690cec23761a38c948b0cb8757550ded54acef
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-beam-samza/uc4-beam-samza-benchmark-operator.yaml
@@ -0,0 +1,68 @@
+apiVersion: theodolite.com/v1
+kind: benchmark
+metadata:
+  name: uc4-beam-samza
+spec:
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc4-beam-samza"
+          files:
+          - "uc4-beam-samza-deployment.yaml"
+          - "beam-samza-service.yaml"
+          - "service-monitor.yaml"
+    afterActions:
+      - selector: # delete zookeeper nodes to reset zookeeper
+          pod:
+            matchLabels:
+              app: "zookeeper-client"
+          container: "zookeeper-client"
+        exec:
+          command: ["bash", "-c", "bin/zkCli.sh -server $ZOOKEEPER_SERVER deleteall /app-theodolite-uc4-application-1"]
+          timeoutSeconds: 60
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc4-load-generator"
+          files:
+          - "uc4-load-generator-deployment.yaml"
+          - "uc4-load-generator-service.yaml"
+  resourceTypes:
+    - typeName: "Instances"
+      patchers:
+        - type: "ReplicaPatcher"
+          resource: "uc4-beam-samza-deployment.yaml"
+  loadTypes:
+    - typeName: "NumNestedGroups"
+      patchers:
+        - type: "EnvVarPatcher"
+          resource: "uc4-load-generator-deployment.yaml"
+          properties:
+            container: "workload-generator"
+            variableName: "NUM_NESTED_GROUPS"
+        - type: NumNestedGroupsLoadGeneratorReplicaPatcher
+          resource: "uc4-load-generator-deployment.yaml"
+          properties:
+            loadGenMaxRecords: "150000"
+            numSensors: "4.0"
+  kafkaConfig:
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
+    topics:
+      - name: "input"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "output"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "configuration"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "aggregation-feedback"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "theodolite-.*"
+        removeOnly: True
+      - name: ".*samza.*"
+        removeOnly: true
+      - name: ".*uc4-application.*"
+        removeOnly: true
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc4-flink/resources/jobmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc4-flink/resources/jobmanager-deployment.yaml
index 032499ea498f8155fd80e42ec4cbdd850498b217..d7037e2c579d82485bb31c53f132d7938f424b38 100644
--- a/theodolite-benchmarks/definitions/uc4-flink/resources/jobmanager-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc4-flink/resources/jobmanager-deployment.yaml
@@ -20,7 +20,7 @@ spec:
           image: ghcr.io/cau-se/theodolite-uc4-flink:latest
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
             - name: COMMIT_INTERVAL_MS
@@ -46,7 +46,7 @@ spec:
             limits:
               memory: 4Gi
               cpu: 1000m
-          args: ["standalone-job", "--job-classname", "theodolite.uc4.application.AggregationServiceFlinkJob"] # optional arguments: ["--job-id", "<job id>", "--fromSavepoint", "/path/to/savepoint", "--allowNonRestoredState"]
+          args: ["standalone-job", "--job-classname", "rocks.theodolite.benchmarks.uc4.flink.AggregationServiceFlinkJob"] # optional arguments: ["--job-id", "<job id>", "--fromSavepoint", "/path/to/savepoint", "--allowNonRestoredState"]
           #command: ['sleep', '60m']
           ports:
             - containerPort: 6123
diff --git a/theodolite-benchmarks/definitions/uc4-flink/resources/taskmanager-deployment.yaml b/theodolite-benchmarks/definitions/uc4-flink/resources/taskmanager-deployment.yaml
index 7af13f20b6b2edf3c8878adf4f381dc1c1add115..cc1efa23c32220c7c664d8aaa4669f3af6492d15 100644
--- a/theodolite-benchmarks/definitions/uc4-flink/resources/taskmanager-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc4-flink/resources/taskmanager-deployment.yaml
@@ -17,10 +17,10 @@ spec:
       terminationGracePeriodSeconds: 0
       containers:
         - name: taskmanager
-          image: ghcr.io/cau-se/theodolite-uc4-flink:latest
+          image: ghcr.io/cau-se/theodolite-uc3-flink:latest
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
             - name: COMMIT_INTERVAL_MS
diff --git a/theodolite-benchmarks/definitions/uc4-flink/uc4-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc4-flink/uc4-flink-benchmark-operator.yaml
index 8a73f5b0f87198def7b152ea52008e3d4a1aa4ee..28ae937e964127ded0e34d637ab307fa08db8ec3 100644
--- a/theodolite-benchmarks/definitions/uc4-flink/uc4-flink-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc4-flink/uc4-flink-benchmark-operator.yaml
@@ -51,7 +51,7 @@ spec:
             loadGenMaxRecords: "150000"
             numSensors: "4.0"
   kafkaConfig:
-    bootstrapServer: "theodolite-cp-kafka:9092"
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
     topics:
       - name: "input"
         numPartitions: 40
diff --git a/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-hazelcastjet-deployment.yaml b/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-hazelcastjet-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f0736e585400d26481272d5b3d75cd216d55527d
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-hazelcastjet-deployment.yaml
@@ -0,0 +1,40 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: titan-ccp-aggregation
+spec:
+  selector:
+    matchLabels:
+      app: titan-ccp-aggregation
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: titan-ccp-aggregation
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: uc-application
+          image: uc4-hazelcastjet
+          imagePullPolicy: "Never"
+          env:
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-kafka-kafka-bootstrap:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: COMMIT_INTERVAL_MS # Set as default for the applications
+              value: "100"
+            - name: WINDOW_SIZE
+              value: "5000"
+            #- name: KUBERNETES_DNS_NAME
+            #  value: "titan-ccp-aggregation"
+            - name: KUBERNETES_NAMESPACE
+              valueFrom:
+                fieldRef:
+                  fieldPath: metadata.namespace
+            - name: KUBERNETES_DNS_NAME
+              value: "titan-ccp-aggregation.$(KUBERNETES_NAMESPACE).svc.cluster.local"
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
\ No newline at end of file
diff --git a/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-hazelcastjet-service.yaml b/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-hazelcastjet-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..845ce7dd55c6e5d45724ec1eeabf8789e704fe77
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-hazelcastjet-service.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Service
+metadata:  
+  name: titan-ccp-aggregation
+  labels:
+    app: titan-ccp-aggregation
+spec:
+  type: ClusterIP
+  clusterIP: None
+  selector:    
+    app: titan-ccp-aggregation
+  ports:  
+    - name: coordination
+      port: 5701
+      targetPort: 5701
+      protocol: TCP
diff --git a/theodolite-benchmarks/definitions/uc4-hazelcastjet/uc4-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc4-hazelcastjet/uc4-benchmark-operator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f0151969ccb2ff34558c4a56c78f17db9fd3678e
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-hazelcastjet/uc4-benchmark-operator.yaml
@@ -0,0 +1,54 @@
+apiVersion: theodolite.com/v1
+kind: benchmark
+metadata:
+  name: uc4-hazelcastjet
+spec:
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc4-hazelcastjet"
+          files:
+            - "uc4-hazelcastjet-deployment.yaml"
+            - "uc4-hazelcastjet-service.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc4-load-generator"
+          files:
+            - "uc4-load-generator-deployment.yaml"
+            - "uc4-load-generator-service.yaml"
+  resourceTypes:
+    - typeName: "Instances"
+      patchers:
+        - type: "ReplicaPatcher"
+          resource: "uc4-hazelcastjet-deployment.yaml"
+  loadTypes:
+    - typeName: "NumNestedGroups"
+      patchers:
+        - type: "EnvVarPatcher"
+          resource: "uc4-load-generator-deployment.yaml"
+          properties:
+            container: "workload-generator"
+            variableName: "NUM_SENSORS"
+        - type: NumNestedGroupsLoadGeneratorReplicaPatcher
+          resource: "uc4-load-generator-deployment.yaml"
+          properties:
+            loadGenMaxRecords: "150000"
+            numSensors: "4.0"
+  kafkaConfig:
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
+    topics:
+      - name: "input"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "output"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "configuration"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "aggregation-feedback"
+        numPartitions: 40
+        replicationFactor: 1
+      - name: "theodolite-.*"
+        removeOnly: True
diff --git a/theodolite-benchmarks/definitions/uc4-kstreams/resources/uc4-kstreams-deployment.yaml b/theodolite-benchmarks/definitions/uc4-kstreams/resources/uc4-kstreams-deployment.yaml
index 20e0872d262df46b5c213d9d529983f5f4155735..3c9a96e36ebf31397f91930426fc028be9d5a2c6 100644
--- a/theodolite-benchmarks/definitions/uc4-kstreams/resources/uc4-kstreams-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc4-kstreams/resources/uc4-kstreams-deployment.yaml
@@ -21,7 +21,7 @@ spec:
               name: jmx
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
             - name: JAVA_OPTS
diff --git a/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-operator.yaml
index 655db2fd4122c9e0e844eed3bfe7c0a878c6d7ec..9ce6daa2dc14e8beecba1c43381defea6bba0d37 100644
--- a/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-operator.yaml
@@ -38,7 +38,7 @@ spec:
             loadGenMaxRecords: "150000"
             numSensors: "4.0"
   kafkaConfig:
-    bootstrapServer: "theodolite-cp-kafka:9092"
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
     topics:
       - name: "input"
         numPartitions: 40
diff --git a/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-standalone.yaml b/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-standalone.yaml
index 5c50b6f95d796941c0b2830549ef825f4a4ff6fb..afed6115102499f225b11c25633e07168a903ea8 100644
--- a/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-standalone.yaml
+++ b/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-standalone.yaml
@@ -34,7 +34,7 @@ loadTypes:
           loadGenMaxRecords: "150000"
           numSensors: "4.0"
 kafkaConfig:
-  bootstrapServer: "theodolite-cp-kafka:9092"
+  bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
   topics:
     - name: "input"
       numPartitions: 40
diff --git a/theodolite-benchmarks/definitions/uc4-load-generator/resources/uc4-load-generator-deployment.yaml b/theodolite-benchmarks/definitions/uc4-load-generator/resources/uc4-load-generator-deployment.yaml
index 7a69d13daae57b06c77f316da9aa953b21ac096b..70674757ff97b4377902395868eac2e03070c31a 100644
--- a/theodolite-benchmarks/definitions/uc4-load-generator/resources/uc4-load-generator-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc4-load-generator/resources/uc4-load-generator-deployment.yaml
@@ -27,8 +27,10 @@ spec:
             - name: KUBERNETES_DNS_NAME
               value: "titan-ccp-load-generator.$(KUBERNETES_NAMESPACE).svc.cluster.local"
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
+            - name: NUM_SENSORS
+              value: "4"
             - name: NUM_NESTED_GROUPS
               value: "5"
diff --git a/theodolite-benchmarks/docker-test/README.md b/theodolite-benchmarks/docker-test/README.md
index fd1e9bf4730f897273be45a022ad2adeae1b7e6e..5d7ca3f4ac470202579f154fe8f066a246c84d23 100644
--- a/theodolite-benchmarks/docker-test/README.md
+++ b/theodolite-benchmarks/docker-test/README.md
@@ -36,3 +36,19 @@ the host, for example, from the IDE or Gradle. In such cases, the following adju
 
 You can now connect to Kafka from your host system with bootstrap server `localhost:19092` and contact the Schema
 Registry via `localhost:8081`. **Pay attention to the Kafka port, which is *19092* instead of the default one *9092*.**
+
+## Running Smoke Tests
+
+The `smoketest-runner.sh` script can be used to run a simple test for a specific Docker Compose file. You can call it with
+
+```sh
+./smoketest-runner.sh <docker-compose-dir>
+```
+
+where `<docker-compose-dir>` is the directory of a Docker-Compose file, for example, `uc2-beam-samza`. The script exists with a zero exit code in case of success and a non-zero exit code otherwise.
+
+You can also run the set of all smoke test with:
+
+```sh
+./smoketest-runner-all.sh
+```
diff --git a/theodolite-benchmarks/docker-test/smoketest-runner-all.sh b/theodolite-benchmarks/docker-test/smoketest-runner-all.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0129a485d98a90d453b284408b755986f64208de
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/smoketest-runner-all.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+find . -name 'test.sh' -type f -exec dirname {} \; |
+    sort |
+    xargs -I %s sh -c "./smoketest-runner.sh %s 1>&2; echo $?" |
+    sort |
+    awk 'BEGIN {count[0]=0; count[1]=0} {count[$1!=0]++} END {print count[0] " tests successful, " count[1] " test failed."; exit count[1]}'
diff --git a/theodolite-benchmarks/docker-test/smoketest-runner.sh b/theodolite-benchmarks/docker-test/smoketest-runner.sh
new file mode 100755
index 0000000000000000000000000000000000000000..1661560bda9cf164dc19b1b031d9f9c8531345d8
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/smoketest-runner.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+COMPOSE_FILE_PATH=$1
+echo "Run test for '$COMPOSE_FILE_PATH'."
+
+cd $COMPOSE_FILE_PATH
+docker-compose pull -q
+docker-compose up -d kafka zookeeper schema-registry
+sleep 30s
+docker-compose up -d
+sleep 5s
+docker-compose ps
+
+if test -f "./test.sh"; then
+    #timeout --foreground 3m ./test.sh
+    ./test.sh
+    RETURN=$?
+else
+    RETURN=$?
+    echo "test.sh does not exists for '$COMPOSE_FILE_PATH'." 
+fi
+
+docker-compose ps
+
+docker-compose down
+
+if [ $RETURN -eq 0 ]; then
+    echo "Test for '$COMPOSE_FILE_PATH' has passed."
+else
+    echo "Test for '$COMPOSE_FILE_PATH' has failed."
+fi
+
+exit $RETURN
diff --git a/theodolite-benchmarks/docker-test/uc1-beam-flink/docker-compose.yml b/theodolite-benchmarks/docker-test/uc1-beam-flink/docker-compose.yml
index 1b683b4ca65a2582aa6a4d68444c4bbef7895b73..835c0b316e4f0f65becce4946688cb6b92f83b57 100644
--- a/theodolite-benchmarks/docker-test/uc1-beam-flink/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc1-beam-flink/docker-compose.yml
@@ -20,18 +20,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
+    restart: "on-failure"
     expose:
       - "8081"
     #ports:
     #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   load-generator: 
     image: ghcr.io/cau-se/theodolite-uc1-workload-generator:${THEODOLITE_TAG:-latest}
     depends_on:
@@ -48,7 +53,7 @@ services:
       #ports:
       #  - "8080:8081"
       command: >
-        standalone-job --job-classname application.Uc1BeamFlink
+        standalone-job --job-classname rocks.theodolite.benchmarks.uc1.beam.flink.Uc1BeamFlink
         --disableMetrics=true 
         --fasterCopy 
       environment:
diff --git a/theodolite-benchmarks/docker-test/uc1-beam-flink/test.sh b/theodolite-benchmarks/docker-test/uc1-beam-flink/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7c7f11a94f42d56d91d383f27d58ad9a09a918e5
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc1-beam-flink/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+sleep 55s # to let the benchmark and produce some output
+docker-compose logs --tail 100 benchmark-taskmanager |
+    sed -n "s/^.*Record:\s\(\S*\)$/\1/p" |
+    tee /dev/stderr |
+    jq .identifier |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b10\b"
diff --git a/theodolite-benchmarks/docker-test/uc1-beam-samza/docker-compose.yml b/theodolite-benchmarks/docker-test/uc1-beam-samza/docker-compose.yml
index f5213799daa2d51eea53e794becdffc151a4da56..2212c3b539045114f31760d605ad928e237ed924 100644
--- a/theodolite-benchmarks/docker-test/uc1-beam-samza/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc1-beam-samza/docker-compose.yml
@@ -22,18 +22,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
+    restart: "on-failure"
     expose:
       - "8081"
     #ports:
     #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   benchmark:
     image: ghcr.io/cau-se/theodolite-uc1-beam-samza:${THEODOLITE_TAG:-latest}
     scale: 1
diff --git a/theodolite-benchmarks/docker-test/uc1-beam-samza/test.sh b/theodolite-benchmarks/docker-test/uc1-beam-samza/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..62327e860cb658741d0892052f5202df3f5b431e
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc1-beam-samza/test.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+sleep 55s # to let the benchmark and produce some output
+docker-compose logs --tail 100 benchmark |
+    sed -n "s/^.*Record:\s\(\S*\)$/\1/p" |
+    tee /dev/stderr |
+    jq .identifier |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b10\b"
+
+
diff --git a/theodolite-benchmarks/docker-test/uc1-flink-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc1-flink/docker-compose.yml
similarity index 85%
rename from theodolite-benchmarks/docker-test/uc1-flink-docker-compose/docker-compose.yml
rename to theodolite-benchmarks/docker-test/uc1-flink/docker-compose.yml
index 6c661bb49cb4173357acc89c06783fe5e0a2ce49..ee6cb06cce228e107fac93a47401718a24bccecd 100755
--- a/theodolite-benchmarks/docker-test/uc1-flink-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc1-flink/docker-compose.yml
@@ -1,4 +1,4 @@
-version: '2'
+version: '2.2'
 services:
   zookeeper:
     image: confluentinc/cp-zookeeper
@@ -20,18 +20,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
+    restart: "on-failure"
     expose:
       - "8081"
     #ports:
     #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   load-generator: 
     image: ghcr.io/cau-se/theodolite-uc1-workload-generator:${THEODOLITE_TAG:-latest}
     depends_on:
@@ -47,7 +52,7 @@ services:
     image: ghcr.io/cau-se/theodolite-uc1-flink:${THEODOLITE_TAG:-latest}
     #ports:
     #  - "8080:8081"
-    command: standalone-job --job-classname theodolite.uc1.application.HistoryServiceFlinkJob
+    command: standalone-job --job-classname rocks.theodolite.benchmarks.uc1.flink.HistoryServiceFlinkJob
     environment:
       - KAFKA_BOOTSTRAP_SERVERS=kafka:9092
       - SCHEMA_REGISTRY_URL=http://schema-registry:8081
diff --git a/theodolite-benchmarks/docker-test/uc1-flink/test.sh b/theodolite-benchmarks/docker-test/uc1-flink/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7c7f11a94f42d56d91d383f27d58ad9a09a918e5
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc1-flink/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+sleep 55s # to let the benchmark and produce some output
+docker-compose logs --tail 100 benchmark-taskmanager |
+    sed -n "s/^.*Record:\s\(\S*\)$/\1/p" |
+    tee /dev/stderr |
+    jq .identifier |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b10\b"
diff --git a/theodolite-benchmarks/docker-test/uc1-hazelcastjet/docker-compose.yml b/theodolite-benchmarks/docker-test/uc1-hazelcastjet/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..fd91f14e241f952dc0d0ba3b4230db2f5deffa30
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc1-hazelcastjet/docker-compose.yml
@@ -0,0 +1,63 @@
+version: '2.2'
+services:
+  zookeeper:
+    image: confluentinc/cp-zookeeper
+    expose:
+      - "2181"
+    environment:
+      ZOOKEEPER_CLIENT_PORT: 2181
+  kafka:
+    image: wurstmeister/kafka
+    expose:
+      - "9092"
+    #ports:
+    #  - 19092:19092
+    environment:
+      KAFKA_LISTENERS: PLAINTEXT://:9092,CONNECTIONS_FROM_HOST://:19092
+      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,CONNECTIONS_FROM_HOST://localhost:19092
+      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONNECTIONS_FROM_HOST:PLAINTEXT
+      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
+      KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
+      KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
+      KAFKA_CREATE_TOPICS: "input:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
+  schema-registry:
+    image: confluentinc/cp-schema-registry:7.0.1
+    depends_on:
+      - zookeeper
+      - kafka
+    restart: "on-failure"
+    expose:
+      - "8081"
+    #ports:
+    #  - 8081:8081
+    environment:
+      SCHEMA_REGISTRY_HOST_NAME: schema-registry
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
+  benchmark:
+    image: ghcr.io/cau-se/theodolite-uc1-hazelcastjet:${THEODOLITE_TAG:-latest}
+    depends_on:
+      - schema-registry
+      - kafka
+    expose:
+      - 5701
+    #ports:
+    #  - 5701:5701
+    environment:
+      BOOTSTRAP_SERVER: benchmark:5701
+      KAFKA_BOOTSTRAP_SERVERS: kafka:9092
+      SCHEMA_REGISTRY_URL: http://schema-registry:8081
+  load-generator: 
+    image: ghcr.io/cau-se/theodolite-uc1-workload-generator:${THEODOLITE_TAG:-latest}
+    depends_on:
+      - schema-registry
+      - kafka
+    environment:
+      BOOTSTRAP_SERVER: load-generator:5701
+      PORT: 5701
+      KAFKA_BOOTSTRAP_SERVERS: kafka:9092
+      SCHEMA_REGISTRY_URL: http://schema-registry:8081
+      NUM_SENSORS: 10
diff --git a/theodolite-benchmarks/docker-test/uc1-hazelcastjet/test.sh b/theodolite-benchmarks/docker-test/uc1-hazelcastjet/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..3dbf43a74a9ad17784ca9e4e476dc70ed11c731f
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc1-hazelcastjet/test.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+sleep 55s # to let the benchmark and produce some output
+
+docker-compose logs --tail 100 benchmark |
+    sed -n "s/^.*Record:\s\(\S*\)$/\1/p" |
+    tee /dev/stderr |
+    jq .identifier |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b10\b"
diff --git a/theodolite-benchmarks/docker-test/uc1-kstreams-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc1-kstreams/docker-compose.yml
similarity index 86%
rename from theodolite-benchmarks/docker-test/uc1-kstreams-docker-compose/docker-compose.yml
rename to theodolite-benchmarks/docker-test/uc1-kstreams/docker-compose.yml
index 25c19e35e5dae1807ef46fb8ade4e888dff0c2d8..a673db5ced5b834632a1bca6f3fb4a2da2b68296 100755
--- a/theodolite-benchmarks/docker-test/uc1-kstreams-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc1-kstreams/docker-compose.yml
@@ -1,4 +1,4 @@
-version: '2'
+version: '2.2'
 services:
   zookeeper:
     image: confluentinc/cp-zookeeper
@@ -20,18 +20,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
+    restart: "on-failure"
     expose:
       - "8081"
     #ports:
     #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   benchmark:
     image: ghcr.io/cau-se/theodolite-uc1-kstreams-app:${THEODOLITE_TAG:-latest}
     depends_on:
diff --git a/theodolite-benchmarks/docker-test/uc1-kstreams/test.sh b/theodolite-benchmarks/docker-test/uc1-kstreams/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..da711e3fac1b1d664b1c8487687ceacdddce6efa
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc1-kstreams/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+sleep 55s # to let the benchmark and produce some output
+docker-compose logs --tail 100 benchmark |
+    sed -n "s/^.*Record:\s\(\S*\)$/\1/p" |
+    tee /dev/stderr |
+    jq .identifier |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b10\b"
diff --git a/theodolite-benchmarks/docker-test/uc2-beam-flink/docker-compose.yml b/theodolite-benchmarks/docker-test/uc2-beam-flink/docker-compose.yml
index 8427161e43faa920e011973d76f32f9cc9d62f8c..e92c09e7822acc93554f47b40debb5d4ea7c0f78 100644
--- a/theodolite-benchmarks/docker-test/uc2-beam-flink/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc2-beam-flink/docker-compose.yml
@@ -20,18 +20,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1,output:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
+    restart: "on-failure"
     expose:
       - "8081"
     #ports:
     #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   load-generator: 
     image: ghcr.io/cau-se/theodolite-uc2-workload-generator:${THEODOLITE_TAG:-latest}
     depends_on:
@@ -48,7 +53,7 @@ services:
       #ports:
       #  - "8080:8081"
       command: >
-        standalone-job --job-classname application.Uc2BeamFlink
+        standalone-job --job-classname rocks.theodolite.benchmarks.uc2.beam.flink.Uc2BeamFlink
         --disableMetrics=true 
         --fasterCopy 
       environment:
diff --git a/theodolite-benchmarks/docker-test/uc2-beam-flink/test.sh b/theodolite-benchmarks/docker-test/uc2-beam-flink/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..3c33834b0b21bc5dbe4e6a7c3ff947121bb2ce71
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc2-beam-flink/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done
+
+docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=s -r http://schema-registry:8081 -f '%k:%s\n' -c 20 |
+    tee /dev/stderr |
+    awk -F ':' '!/^%/ {print $1}' |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b10\b"
diff --git a/theodolite-benchmarks/docker-test/uc2-beam-samza/docker-compose.yml b/theodolite-benchmarks/docker-test/uc2-beam-samza/docker-compose.yml
index 820bb25dd370cf6c7410b20fbdbdb1d4281f47d3..cc6bc7a7112c35f11ce9cfd27d09aebe401c8c51 100644
--- a/theodolite-benchmarks/docker-test/uc2-beam-samza/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc2-beam-samza/docker-compose.yml
@@ -22,18 +22,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1,output:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
+    restart: "on-failure"
     expose:
       - "8081"
     #ports:
     #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   benchmark:
     image: ghcr.io/cau-se/theodolite-uc2-beam-samza:${THEODOLITE_TAG:-latest}
     scale: 1
diff --git a/theodolite-benchmarks/docker-test/uc2-beam-samza/test.sh b/theodolite-benchmarks/docker-test/uc2-beam-samza/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..3c33834b0b21bc5dbe4e6a7c3ff947121bb2ce71
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc2-beam-samza/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done
+
+docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=s -r http://schema-registry:8081 -f '%k:%s\n' -c 20 |
+    tee /dev/stderr |
+    awk -F ':' '!/^%/ {print $1}' |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b10\b"
diff --git a/theodolite-benchmarks/docker-test/uc2-flink-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc2-flink/docker-compose.yml
similarity index 84%
rename from theodolite-benchmarks/docker-test/uc2-flink-docker-compose/docker-compose.yml
rename to theodolite-benchmarks/docker-test/uc2-flink/docker-compose.yml
index e51c544bfd64c6f540f5a84a5f617de745a1a6b6..a68b8084669c45ead3e08bf493ca32efdb234504 100755
--- a/theodolite-benchmarks/docker-test/uc2-flink-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc2-flink/docker-compose.yml
@@ -1,4 +1,4 @@
-version: '2'
+version: '2.2'
 services:
   zookeeper:
     image: confluentinc/cp-zookeeper
@@ -20,18 +20,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1,output:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
-    #ports:
-    #  - "8081:8081"
+    restart: "on-failure"
     expose:
       - "8081"
+    #ports:
+    #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   load-generator: 
     image: ghcr.io/cau-se/theodolite-uc2-workload-generator:${THEODOLITE_TAG:-latest}
     depends_on:
@@ -47,7 +52,7 @@ services:
     image: ghcr.io/cau-se/theodolite-uc2-flink:${THEODOLITE_TAG:-latest}
     #ports:
     #  - "8080:8081"
-    command: standalone-job --job-classname theodolite.uc2.application.HistoryServiceFlinkJob
+    command: standalone-job --job-classname rocks.theodolite.benchmarks.uc2.flink.HistoryServiceFlinkJob
     environment:
       - KAFKA_BOOTSTRAP_SERVERS=kafka:9092
       - SCHEMA_REGISTRY_URL=http://schema-registry:8081
diff --git a/theodolite-benchmarks/docker-test/uc2-flink/test.sh b/theodolite-benchmarks/docker-test/uc2-flink/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..3c33834b0b21bc5dbe4e6a7c3ff947121bb2ce71
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc2-flink/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done
+
+docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=s -r http://schema-registry:8081 -f '%k:%s\n' -c 20 |
+    tee /dev/stderr |
+    awk -F ':' '!/^%/ {print $1}' |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b10\b"
diff --git a/theodolite-benchmarks/docker-test/uc2-hazelcastjet/docker-compose.yml b/theodolite-benchmarks/docker-test/uc2-hazelcastjet/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..92b90823e31f79e68b301ff039618c9520c92019
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc2-hazelcastjet/docker-compose.yml
@@ -0,0 +1,64 @@
+version: '2.2'
+services:
+  zookeeper:
+    image: confluentinc/cp-zookeeper
+    expose:
+      - "2181"
+    environment:
+      ZOOKEEPER_CLIENT_PORT: 2181
+  kafka:
+    image: wurstmeister/kafka
+    expose:
+      - "9092"
+    #ports:
+    #  - 19092:19092
+    environment:
+      KAFKA_LISTENERS: PLAINTEXT://:9092,CONNECTIONS_FROM_HOST://:19092
+      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,CONNECTIONS_FROM_HOST://localhost:19092
+      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONNECTIONS_FROM_HOST:PLAINTEXT
+      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
+      KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
+      KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
+      KAFKA_CREATE_TOPICS: "input:3:1,output:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
+  schema-registry:
+    image: confluentinc/cp-schema-registry:7.0.1
+    depends_on:
+      - zookeeper
+      - kafka
+    restart: "on-failure"
+    expose:
+      - "8081"
+    #ports:
+    #  - 8081:8081
+    environment:
+      SCHEMA_REGISTRY_HOST_NAME: schema-registry
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
+  benchmark:
+    image: ghcr.io/cau-se/theodolite-uc2-hazelcastjet:${THEODOLITE_TAG:-latest}
+    depends_on:
+      - schema-registry
+      - kafka
+    expose:
+      - 5701
+    #ports:
+    #  - 5701:5701
+    environment:
+      BOOTSTRAP_SERVER: benchmark:5701
+      KAFKA_BOOTSTRAP_SERVERS: kafka:9092
+      SCHEMA_REGISTRY_URL: http://schema-registry:8081
+      DOWNSAMPLE_INTERVAL: 5000
+  load-generator: 
+    image: ghcr.io/cau-se/theodolite-uc2-workload-generator:${THEODOLITE_TAG:-latest}
+    depends_on:
+      - schema-registry
+      - kafka
+    environment:
+      BOOTSTRAP_SERVER: load-generator:5701
+      PORT: 5701
+      KAFKA_BOOTSTRAP_SERVERS: kafka:9092
+      SCHEMA_REGISTRY_URL: http://schema-registry:8081
+      NUM_SENSORS: 10
diff --git a/theodolite-benchmarks/docker-test/uc2-hazelcastjet/test.sh b/theodolite-benchmarks/docker-test/uc2-hazelcastjet/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..be411755b74249d90756e445f7e67dc07bf5ebab
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc2-hazelcastjet/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done
+
+docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=s -r http://schema-registry:8081 -f '%k:%s\n' -c 20 |
+    tee /dev/stderr |
+    awk -F ':' '!/^%/ {print $1}' |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b10\b"
\ No newline at end of file
diff --git a/theodolite-benchmarks/docker-test/uc2-kstreams-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc2-kstreams/docker-compose.yml
similarity index 86%
rename from theodolite-benchmarks/docker-test/uc2-kstreams-docker-compose/docker-compose.yml
rename to theodolite-benchmarks/docker-test/uc2-kstreams/docker-compose.yml
index 4cc4978d844a8b361af4061ab41d1adc4e7a1813..efdba90bef634bab76012316f67b0f9be9f79c77 100755
--- a/theodolite-benchmarks/docker-test/uc2-kstreams-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc2-kstreams/docker-compose.yml
@@ -1,4 +1,4 @@
-version: '2'
+version: '2.2'
 services:
   zookeeper:
     image: confluentinc/cp-zookeeper
@@ -20,18 +20,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1,output:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
-    #ports:
-    #  - "8081:8081"
+    restart: "on-failure"
     expose:
       - "8081"
+    #ports:
+    #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   benchmark:
     image: ghcr.io/cau-se/theodolite-uc2-kstreams-app:${THEODOLITE_TAG:-latest}
     depends_on:
diff --git a/theodolite-benchmarks/docker-test/uc2-kstreams/test.sh b/theodolite-benchmarks/docker-test/uc2-kstreams/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..3c33834b0b21bc5dbe4e6a7c3ff947121bb2ce71
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc2-kstreams/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done
+
+docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=s -r http://schema-registry:8081 -f '%k:%s\n' -c 20 |
+    tee /dev/stderr |
+    awk -F ':' '!/^%/ {print $1}' |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b10\b"
diff --git a/theodolite-benchmarks/docker-test/uc3-beam-flink/docker-compose.yml b/theodolite-benchmarks/docker-test/uc3-beam-flink/docker-compose.yml
index b9e934b61f9742ad4e83601ff13707be0641c875..4416517a8db0814234536793bc262530103b45b3 100644
--- a/theodolite-benchmarks/docker-test/uc3-beam-flink/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc3-beam-flink/docker-compose.yml
@@ -20,18 +20,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1,output:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
+    restart: "on-failure"
     expose:
       - "8081"
     #ports:
     #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   load-generator: 
     image: ghcr.io/cau-se/theodolite-uc3-workload-generator:${THEODOLITE_TAG:-latest}
     depends_on:
@@ -48,7 +53,7 @@ services:
       #ports:
       #  - "8080:8081"
       command: >
-        standalone-job --job-classname application.Uc3BeamFlink
+        standalone-job --job-classname rocks.theodolite.benchmarks.uc3.beam.flink.Uc3BeamFlink
         --disableMetrics=true 
         --fasterCopy 
       environment:
diff --git a/theodolite-benchmarks/docker-test/uc3-beam-flink/test.sh b/theodolite-benchmarks/docker-test/uc3-beam-flink/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0612838a3973a302c9acb3bbfa6b8d59ea2596c5
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc3-beam-flink/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done
+
+docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=s -r http://schema-registry:8081 -f '%k:%s\n' -c 600 |
+    tee /dev/stderr |
+    awk -F ':' '!/^%/ {print $1}' |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b10\b"
diff --git a/theodolite-benchmarks/docker-test/uc3-beam-samza/docker-compose.yml b/theodolite-benchmarks/docker-test/uc3-beam-samza/docker-compose.yml
index 3ae3a2faa7c0849b76ea838b09ba0254bdfea936..bf120f31dbfda2384b314ba4a90a25362f37b6c2 100644
--- a/theodolite-benchmarks/docker-test/uc3-beam-samza/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc3-beam-samza/docker-compose.yml
@@ -22,18 +22,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1,output:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
+    restart: "on-failure"
     expose:
       - "8081"
     #ports:
     #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   benchmark:
     image: ghcr.io/cau-se/theodolite-uc3-beam-samza:${THEODOLITE_TAG:-latest}
     scale: 1
diff --git a/theodolite-benchmarks/docker-test/uc3-beam-samza/test.sh b/theodolite-benchmarks/docker-test/uc3-beam-samza/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0612838a3973a302c9acb3bbfa6b8d59ea2596c5
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc3-beam-samza/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done
+
+docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=s -r http://schema-registry:8081 -f '%k:%s\n' -c 600 |
+    tee /dev/stderr |
+    awk -F ':' '!/^%/ {print $1}' |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b10\b"
diff --git a/theodolite-benchmarks/docker-test/uc3-flink-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc3-flink/docker-compose.yml
similarity index 84%
rename from theodolite-benchmarks/docker-test/uc3-flink-docker-compose/docker-compose.yml
rename to theodolite-benchmarks/docker-test/uc3-flink/docker-compose.yml
index 42c55950fbea022f00019699ae72678fbe88b8cb..3c5aadd8fb6b3b40b009808f55659982dd837f52 100755
--- a/theodolite-benchmarks/docker-test/uc3-flink-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc3-flink/docker-compose.yml
@@ -1,4 +1,4 @@
-version: '2'
+version: '2.2'
 services:
   zookeeper:
     image: confluentinc/cp-zookeeper
@@ -20,18 +20,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1,output:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
-    #ports:
-    #  - "8081:8081"
+    restart: "on-failure"
     expose:
       - "8081"
+    #ports:
+    #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   load-generator: 
     image: ghcr.io/cau-se/theodolite-uc3-workload-generator:${THEODOLITE_TAG:-latest}
     depends_on:
@@ -47,7 +52,7 @@ services:
     image: ghcr.io/cau-se/theodolite-uc3-flink:${THEODOLITE_TAG:-latest}
     #ports:
     #  - "8080:8081"
-    command: standalone-job --job-classname theodolite.uc3.application.HistoryServiceFlinkJob
+    command: standalone-job --job-classname rocks.theodolite.benchmarks.uc3.flink.HistoryServiceFlinkJob
     environment:
       - KAFKA_BOOTSTRAP_SERVERS=kafka:9092
       - SCHEMA_REGISTRY_URL=http://schema-registry:8081
diff --git a/theodolite-benchmarks/docker-test/uc3-hazelcastjet/docker-compose.yml b/theodolite-benchmarks/docker-test/uc3-hazelcastjet/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d7c3fe7a017c24e0b212661f0b0b34c2a1fee32c
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc3-hazelcastjet/docker-compose.yml
@@ -0,0 +1,65 @@
+version: '2.2'
+services:
+  zookeeper:
+    image: confluentinc/cp-zookeeper
+    expose:
+      - "2181"
+    environment:
+      ZOOKEEPER_CLIENT_PORT: 2181
+  kafka:
+    image: wurstmeister/kafka
+    expose:
+      - "9092"
+    #ports:
+    #  - 19092:19092
+    environment:
+      KAFKA_LISTENERS: PLAINTEXT://:9092,CONNECTIONS_FROM_HOST://:19092
+      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,CONNECTIONS_FROM_HOST://localhost:19092
+      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONNECTIONS_FROM_HOST:PLAINTEXT
+      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
+      KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
+      KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
+      KAFKA_CREATE_TOPICS: "input:3:1,output:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
+  schema-registry:
+    image: confluentinc/cp-schema-registry:7.0.1
+    depends_on:
+      - zookeeper
+      - kafka
+    restart: "on-failure"
+    expose:
+      - "8081"
+    #ports:
+    #  - 8081:8081
+    environment:
+      SCHEMA_REGISTRY_HOST_NAME: schema-registry
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
+  benchmark:
+    image: ghcr.io/cau-se/theodolite-uc3-hazelcastjet:${THEODOLITE_TAG:-latest}
+    depends_on:
+      - schema-registry
+      - kafka
+    expose:
+      - 5701
+    #ports:
+    #  - 5701:5701
+    environment:
+      BOOTSTRAP_SERVER: benchmark:5701
+      KAFKA_BOOTSTRAP_SERVERS: kafka:9092
+      SCHEMA_REGISTRY_URL: http://schema-registry:8081
+      WINDOW_SIZE_IN_SECONDS: 50
+      HOPPING_SIZE_IN_SECONDS: 5
+  load-generator:
+    image: ghcr.io/cau-se/theodolite-uc3-workload-generator:${THEODOLITE_TAG:-latest}
+    depends_on:
+      - schema-registry
+      - kafka
+    environment:
+      BOOTSTRAP_SERVER: load-generator:5701
+      PORT: 5701
+      KAFKA_BOOTSTRAP_SERVERS: kafka:9092
+      SCHEMA_REGISTRY_URL: http://schema-registry:8081
+      NUM_SENSORS: 10
diff --git a/theodolite-benchmarks/docker-test/uc3-hazelcastjet/test.sh b/theodolite-benchmarks/docker-test/uc3-hazelcastjet/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..217a730f73fa1fee3f875da34edd9047ed9221db
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc3-hazelcastjet/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done
+
+docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=s -r http://schema-registry:8081 -f '%k:%s\n' -c 600 |
+    tee /dev/stderr |
+    awk -F ':' '!/^%/ {print $1}' |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b10\b"
\ No newline at end of file
diff --git a/theodolite-benchmarks/docker-test/uc3-kstreams-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc3-kstreams/docker-compose.yml
similarity index 85%
rename from theodolite-benchmarks/docker-test/uc3-kstreams-docker-compose/docker-compose.yml
rename to theodolite-benchmarks/docker-test/uc3-kstreams/docker-compose.yml
index f943de372b75bf64df0028679d56950fedfaec48..7da1fa3b420e2dfa0d6d357723583bc3a256823e 100755
--- a/theodolite-benchmarks/docker-test/uc3-kstreams-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc3-kstreams/docker-compose.yml
@@ -1,4 +1,4 @@
-version: '2'
+version: '2.2'
 services:
   zookeeper:
     image: confluentinc/cp-zookeeper
@@ -20,18 +20,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1,output:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
-    #ports:
-    #  - "8081:8081"
+    restart: "on-failure"
     expose:
       - "8081"
+    #ports:
+    #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   benchmark:
     image: ghcr.io/cau-se/theodolite-uc3-kstreams-app:${THEODOLITE_TAG:-latest}
     depends_on:
diff --git a/theodolite-benchmarks/docker-test/uc3-kstreams/test.sh b/theodolite-benchmarks/docker-test/uc3-kstreams/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0612838a3973a302c9acb3bbfa6b8d59ea2596c5
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc3-kstreams/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done
+
+docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=s -r http://schema-registry:8081 -f '%k:%s\n' -c 600 |
+    tee /dev/stderr |
+    awk -F ':' '!/^%/ {print $1}' |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b10\b"
diff --git a/theodolite-benchmarks/docker-test/uc4-beam-flink/docker-compose.yml b/theodolite-benchmarks/docker-test/uc4-beam-flink/docker-compose.yml
index b0d18dfe34c23847b3cc0b04d788fdc4b3552e68..465fcb6ee6a2b2121dfe359140c259e7a3eb763a 100644
--- a/theodolite-benchmarks/docker-test/uc4-beam-flink/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc4-beam-flink/docker-compose.yml
@@ -20,18 +20,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1,output:3:1,configuration:3:1,aggregation-feedback:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
+    restart: "on-failure"
     expose:
       - "8081"
     #ports:
     #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   load-generator: 
     image: ghcr.io/cau-se/theodolite-uc4-workload-generator:${THEODOLITE_TAG:-latest}
     depends_on:
@@ -43,14 +48,14 @@ services:
       KAFKA_BOOTSTRAP_SERVERS: kafka:9092
       SCHEMA_REGISTRY_URL: http://schema-registry:8081
       NUM_SENSORS: 4
-      NUM_NESTED_GROUPS: 4
+      NUM_NESTED_GROUPS: 3
   benchmark-jobmanager:
       image: ghcr.io/cau-se/theodolite-uc4-beam-flink:${THEODOLITE_TAG:-latest}
       #ports:
       #  - "8080:8081"
       command: >
         standalone-job
-        --job-classname application.Uc4BeamFlink
+        --job-classname rocks.theodolite.benchmarks.uc4.beam.flink.Uc4BeamFlink
         --disableMetrics=true 
         --fasterCopy 
       environment:
diff --git a/theodolite-benchmarks/docker-test/uc4-beam-flink/test.sh b/theodolite-benchmarks/docker-test/uc4-beam-flink/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..6a4c6dbf4f583e7598baefae8f48136bb2113630
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc4-beam-flink/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done
+
+docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=avro -r http://schema-registry:8081 -f '%k:%s\n' -c 2000 |
+    tee /dev/stderr |
+    awk -F ':' '!/^%/ {print $1}' |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b21\b"
diff --git a/theodolite-benchmarks/docker-test/uc4-beam-samza/docker-compose.yml b/theodolite-benchmarks/docker-test/uc4-beam-samza/docker-compose.yml
index b9e4142cb0be2701f7772cff5725b524aaffcbc7..d236af7d284ebb085c78110feb6001cb28d18290 100644
--- a/theodolite-benchmarks/docker-test/uc4-beam-samza/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc4-beam-samza/docker-compose.yml
@@ -22,18 +22,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1,output:3:1,configuration:3:1,aggregation-feedback:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
+    restart: "on-failure"
     expose:
       - "8081"
     #ports:
     #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   benchmark:
     image: ghcr.io/cau-se/theodolite-uc4-beam-samza:${THEODOLITE_TAG:-latest}
     scale: 1
@@ -57,4 +62,4 @@ services:
       KAFKA_BOOTSTRAP_SERVERS: kafka:9092
       SCHEMA_REGISTRY_URL: http://schema-registry:8081
       NUM_SENSORS: 4
-      NUM_NESTED_GROUPS: 4
+      NUM_NESTED_GROUPS: 3
diff --git a/theodolite-benchmarks/docker-test/uc4-beam-samza/test.sh b/theodolite-benchmarks/docker-test/uc4-beam-samza/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..6a4c6dbf4f583e7598baefae8f48136bb2113630
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc4-beam-samza/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done
+
+docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=avro -r http://schema-registry:8081 -f '%k:%s\n' -c 2000 |
+    tee /dev/stderr |
+    awk -F ':' '!/^%/ {print $1}' |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b21\b"
diff --git a/theodolite-benchmarks/docker-test/uc4-flink-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc4-flink/docker-compose.yml
similarity index 84%
rename from theodolite-benchmarks/docker-test/uc4-flink-docker-compose/docker-compose.yml
rename to theodolite-benchmarks/docker-test/uc4-flink/docker-compose.yml
index 5a5a5924ef13cc9691b267ce6169bdb85a1e267b..c3fe0502f36e3b25857186046e5ed6892f07f61f 100755
--- a/theodolite-benchmarks/docker-test/uc4-flink-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc4-flink/docker-compose.yml
@@ -1,4 +1,4 @@
-version: '2'
+version: '2.2'
 services:
   zookeeper:
     image: confluentinc/cp-zookeeper
@@ -20,18 +20,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1,output:3:1,configuration:3:1,aggregation-feedback:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
+    restart: "on-failure"
     expose:
       - "8081"
     #ports:
     #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   load-generator: 
     image: ghcr.io/cau-se/theodolite-uc4-workload-generator:${THEODOLITE_TAG:-latest}
     depends_on:
@@ -43,12 +48,12 @@ services:
       KAFKA_BOOTSTRAP_SERVERS: kafka:9092
       SCHEMA_REGISTRY_URL: http://schema-registry:8081
       NUM_SENSORS: 4
-      NUM_NESTED_GROUPS: 4
+      NUM_NESTED_GROUPS: 3
   benchmark-jobmanager:
     image: ghcr.io/cau-se/theodolite-uc4-flink:${THEODOLITE_TAG:-latest}
     #ports:
     #  - "8080:8081"
-    command: standalone-job --job-classname theodolite.uc4.application.AggregationServiceFlinkJob
+    command: standalone-job --job-classname rocks.theodolite.benchmarks.uc4.flink.AggregationServiceFlinkJob
     environment:
       - KAFKA_BOOTSTRAP_SERVERS=kafka:9092
       - SCHEMA_REGISTRY_URL=http://schema-registry:8081
diff --git a/theodolite-benchmarks/docker-test/uc4-flink/test.sh b/theodolite-benchmarks/docker-test/uc4-flink/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0a478cf6641a1333f65281ae43cb525e32cb2510
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc4-flink/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done
+
+docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=avro -r http://schema-registry:8081 -f '%k:%s\n' -c 500 |
+    tee /dev/stderr |
+    awk -F ':' '!/^%/ {print $1}' |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b21\b"
diff --git a/theodolite-benchmarks/docker-test/uc4-hazelcastjet/docker-compose.yml b/theodolite-benchmarks/docker-test/uc4-hazelcastjet/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ca6f3c85fe670e53bafd6a56e568cad9166ae501
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc4-hazelcastjet/docker-compose.yml
@@ -0,0 +1,65 @@
+version: '2.2'
+services:
+  zookeeper:
+    image: confluentinc/cp-zookeeper
+    expose:
+      - "2181"
+    environment:
+      ZOOKEEPER_CLIENT_PORT: 2181
+  kafka:
+    image: wurstmeister/kafka
+    expose:
+      - "9092"
+    #ports:
+    #  - 19092:19092
+    environment:
+      KAFKA_LISTENERS: PLAINTEXT://:9092,CONNECTIONS_FROM_HOST://:19092
+      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,CONNECTIONS_FROM_HOST://localhost:19092
+      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONNECTIONS_FROM_HOST:PLAINTEXT
+      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
+      KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
+      KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
+      KAFKA_CREATE_TOPICS: "input:3:1,output:3:1,configuration:3:1,aggregation-feedback:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
+  schema-registry:
+    image: confluentinc/cp-schema-registry:7.0.1
+    depends_on:
+      - zookeeper
+      - kafka
+    restart: "on-failure"
+    expose:
+      - "8081"
+    #ports:
+    #  - 8081:8081
+    environment:
+      SCHEMA_REGISTRY_HOST_NAME: schema-registry
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
+  benchmark:
+    image: ghcr.io/cau-se/theodolite-uc4-hazelcastjet:${THEODOLITE_TAG:-latest}
+    depends_on:
+      - schema-registry
+      - kafka
+    expose:
+      - 5701
+    #ports:
+    #  - 5701:5701
+    environment:
+      BOOTSTRAP_SERVER: benchmark:5701
+      KAFKA_BOOTSTRAP_SERVERS: kafka:9092
+      SCHEMA_REGISTRY_URL: http://schema-registry:8081
+      WINDOW_SIZE_UC4: 5000
+  load-generator: 
+    image: ghcr.io/cau-se/theodolite-uc4-workload-generator:${THEODOLITE_TAG:-latest}
+    depends_on:
+      - schema-registry
+      - kafka
+    environment:
+      BOOTSTRAP_SERVER: load-generator:5701
+      PORT: 5701
+      KAFKA_BOOTSTRAP_SERVERS: kafka:9092
+      SCHEMA_REGISTRY_URL: http://schema-registry:8081
+      NUM_SENSORS: 4
+      NUM_NESTED_GROUPS: 3
diff --git a/theodolite-benchmarks/docker-test/uc4-hazelcastjet/test.sh b/theodolite-benchmarks/docker-test/uc4-hazelcastjet/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..d9bb6ccf241935c39df63ea5e2f0fce02476e976
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc4-hazelcastjet/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done
+
+docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=avro -r http://schema-registry:8081 -f '%k:%s\n' -c 600 |
+    tee /dev/stderr |
+    awk -F ':' '!/^%/ {print $1}' |
+    sort |
+    uniq |
+    wc -l|
+    grep "\b21\b"
\ No newline at end of file
diff --git a/theodolite-benchmarks/docker-test/uc4-kstreams-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc4-kstreams/docker-compose.yml
similarity index 86%
rename from theodolite-benchmarks/docker-test/uc4-kstreams-docker-compose/docker-compose.yml
rename to theodolite-benchmarks/docker-test/uc4-kstreams/docker-compose.yml
index 1818505787f662d57f1a96c8c79b03d61cf9da2a..6aaa02990841547edb6059e4e2fbf3b28b50985c 100755
--- a/theodolite-benchmarks/docker-test/uc4-kstreams-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc4-kstreams/docker-compose.yml
@@ -1,4 +1,4 @@
-version: '2'
+version: '2.2'
 services:
   zookeeper:
     image: confluentinc/cp-zookeeper
@@ -20,18 +20,23 @@ services:
       KAFKA_ZOOKEEPER_CONNECTION_TIMEOUT_MS: 30000
       KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
       KAFKA_CREATE_TOPICS: "input:3:1,output:3:1,configuration:3:1,aggregation-feedback:3:1"
+  kcat:
+    image: edenhill/kcat:1.7.1
+    entrypoint: "sh"
+    tty: true
   schema-registry:
-    image: confluentinc/cp-schema-registry:5.3.1
+    image: confluentinc/cp-schema-registry:7.0.1
     depends_on:
       - zookeeper
       - kafka
+    restart: "on-failure"
     expose:
       - "8081"
     #ports:
     #  - 8081:8081
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
-      SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
+      SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
   benchmark:
     image: ghcr.io/cau-se/theodolite-uc4-kstreams-app:${THEODOLITE_TAG:-latest}
     depends_on:
@@ -51,4 +56,4 @@ services:
       KAFKA_BOOTSTRAP_SERVERS: kafka:9092
       SCHEMA_REGISTRY_URL: http://schema-registry:8081
       NUM_SENSORS: 4
-      NUM_NESTED_GROUPS: 4
\ No newline at end of file
+      NUM_NESTED_GROUPS: 3
\ No newline at end of file
diff --git a/theodolite-benchmarks/docker-test/uc4-kstreams/test.sh b/theodolite-benchmarks/docker-test/uc4-kstreams/test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9b9dee7dc78e7a587b9f2e5b778066e5bc099755
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/uc4-kstreams/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done
+
+docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=avro -r http://schema-registry:8081 -f '%k:%s\n' -c 32 |
+    tee /dev/stderr |
+    awk -F ':' '!/^%/ {print $1}' |
+    sort |
+    uniq |
+    wc -l |
+    grep "\b16\b"
diff --git a/theodolite-benchmarks/flink-commons/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/flink-commons/.settings/org.eclipse.jdt.ui.prefs
index 66b402b58f39b79066638ce679c27c0378d5be54..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/flink-commons/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/flink-commons/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,25 +12,72 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
 cleanup.remove_redundant_semicolons=true
@@ -37,6 +85,7 @@ cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,28 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
 org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -80,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
 sp_cleanup.remove_redundant_semicolons=false
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -115,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/flink-commons/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/flink-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/flink-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/flink-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/flink-commons/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/flink-commons/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/flink-commons/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/flink-commons/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/flink-commons/build.gradle b/theodolite-benchmarks/flink-commons/build.gradle
index a3a4a35752006bb10e15ff508ce0b37f70adc57d..bd07f1ca51ae6b781a92ae06ba8b2555fa83b873 100644
--- a/theodolite-benchmarks/flink-commons/build.gradle
+++ b/theodolite-benchmarks/flink-commons/build.gradle
@@ -3,7 +3,7 @@ plugins {
 }
 
 ext {
-    flinkVersion = '1.12.0'
+    flinkVersion = '1.13.5'
     scalaBinaryVersion = '2.12'
 }
 
diff --git a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/ConfigurationKeys.java b/theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/ConfigurationKeys.java
similarity index 90%
rename from theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/ConfigurationKeys.java
rename to theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/ConfigurationKeys.java
index 2847ede440ecd65bdf35fc8e825d0f7b723a3f8f..8fd8fbde288d1750fb1bab2147885d7be6245316 100644
--- a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/ConfigurationKeys.java
+++ b/theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/ConfigurationKeys.java
@@ -1,4 +1,4 @@
-package theodolite.commons.flink;
+package rocks.theodolite.benchmarks.commons.flink;
 
 /**
  * Keys to access configuration parameters.
diff --git a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/KafkaConnectorFactory.java b/theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/KafkaConnectorFactory.java
similarity index 96%
rename from theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/KafkaConnectorFactory.java
rename to theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/KafkaConnectorFactory.java
index 55d73b0fb9274b0ae67468d50b7978799d7e6257..a17403f07b8dcc9d3034222035428ecae6b7f860 100644
--- a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/KafkaConnectorFactory.java
+++ b/theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/KafkaConnectorFactory.java
@@ -1,4 +1,4 @@
-package theodolite.commons.flink;
+package rocks.theodolite.benchmarks.commons.flink;
 
 import java.time.Duration;
 import java.util.Properties;
@@ -15,8 +15,8 @@ import org.apache.flink.streaming.connectors.kafka.KafkaSerializationSchema;
 import org.apache.kafka.clients.consumer.ConsumerConfig;
 import org.apache.kafka.clients.producer.ProducerConfig;
 import org.apache.kafka.common.serialization.Serde;
-import theodolite.commons.flink.serialization.FlinkKafkaKeyValueSerde;
-import theodolite.commons.flink.util.SerializableSupplier;
+import rocks.theodolite.benchmarks.commons.flink.serialization.FlinkKafkaKeyValueSerde;
+import rocks.theodolite.benchmarks.commons.flink.util.SerializableSupplier;
 
 /**
  * A class for creating {@link FlinkKafkaConsumer} and {@link FlinkKafkaProducer}.
diff --git a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/StateBackends.java b/theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/StateBackends.java
similarity index 98%
rename from theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/StateBackends.java
rename to theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/StateBackends.java
index a94927e4bf49e1dbe6d109eb8f19f7d292f3d879..0f58c9ae8a16842ee077e7c9d01cf69571f11af4 100644
--- a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/StateBackends.java
+++ b/theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/StateBackends.java
@@ -1,4 +1,4 @@
-package theodolite.commons.flink;
+package rocks.theodolite.benchmarks.commons.flink;
 
 import java.io.IOException;
 import org.apache.commons.configuration2.Configuration;
diff --git a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/TupleType.java b/theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/TupleType.java
similarity index 92%
rename from theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/TupleType.java
rename to theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/TupleType.java
index 360331e4d1e4fdc47a24ac8ae995b7590301f7fd..fc2249ae36b5be2c2ffdf114a1f6c1ecad3364d1 100644
--- a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/TupleType.java
+++ b/theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/TupleType.java
@@ -1,4 +1,4 @@
-package theodolite.commons.flink;
+package rocks.theodolite.benchmarks.commons.flink;
 
 import org.apache.flink.api.common.typeinfo.TypeInformation;
 import org.apache.flink.api.common.typeinfo.Types;
diff --git a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/serialization/FlinkKafkaKeyValueSerde.java b/theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/serialization/FlinkKafkaKeyValueSerde.java
similarity index 95%
rename from theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/serialization/FlinkKafkaKeyValueSerde.java
rename to theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/serialization/FlinkKafkaKeyValueSerde.java
index 22f615a6af4caf575af57dbe9b7f989889c4095f..40482a7caf2838e54f42771f743e48cabeeee615 100644
--- a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/serialization/FlinkKafkaKeyValueSerde.java
+++ b/theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/serialization/FlinkKafkaKeyValueSerde.java
@@ -1,4 +1,4 @@
-package theodolite.commons.flink.serialization;
+package rocks.theodolite.benchmarks.commons.flink.serialization;
 
 import javax.annotation.Nullable;
 import org.apache.flink.api.common.typeinfo.TypeInformation;
@@ -8,7 +8,7 @@ import org.apache.flink.streaming.connectors.kafka.KafkaSerializationSchema;
 import org.apache.kafka.clients.consumer.ConsumerRecord;
 import org.apache.kafka.clients.producer.ProducerRecord;
 import org.apache.kafka.common.serialization.Serde;
-import theodolite.commons.flink.util.SerializableSupplier;
+import rocks.theodolite.benchmarks.commons.flink.util.SerializableSupplier;
 
 /**
  * A {@link KafkaSerializationSchema} and {@link KafkaDeserializationSchema} for an arbitrary
diff --git a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/serialization/StatsSerializer.java b/theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/serialization/StatsSerializer.java
similarity index 93%
rename from theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/serialization/StatsSerializer.java
rename to theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/serialization/StatsSerializer.java
index fe74fbe4b9dcb6ce89d10131de1336bfff40a919..881f5870a4dda3085d1391aea016f61018627029 100644
--- a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/serialization/StatsSerializer.java
+++ b/theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/serialization/StatsSerializer.java
@@ -1,4 +1,4 @@
-package theodolite.commons.flink.serialization;
+package rocks.theodolite.benchmarks.commons.flink.serialization;
 
 import com.esotericsoftware.kryo.Kryo;
 import com.esotericsoftware.kryo.Serializer;
diff --git a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/util/SerializableSupplier.java b/theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/util/SerializableSupplier.java
similarity index 84%
rename from theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/util/SerializableSupplier.java
rename to theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/util/SerializableSupplier.java
index bcc51a9ef7b8bb0f36398ea401f1d2c898472081..4697e13eaed444a9f23d8ec44deb386f9c542ace 100644
--- a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/util/SerializableSupplier.java
+++ b/theodolite-benchmarks/flink-commons/src/main/java/rocks/theodolite/benchmarks/commons/flink/util/SerializableSupplier.java
@@ -1,4 +1,4 @@
-package theodolite.commons.flink.util;
+package rocks.theodolite.benchmarks.commons.flink.util;
 
 import java.io.Serializable;
 import java.util.function.Supplier;
diff --git a/theodolite-benchmarks/hazelcastjet-commons/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/hazelcastjet-commons/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/hazelcastjet-commons/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/hazelcastjet-commons/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/hazelcastjet-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/hazelcastjet-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/hazelcastjet-commons/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/hazelcastjet-commons/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/hazelcastjet-commons/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/hazelcastjet-commons/build.gradle b/theodolite-benchmarks/hazelcastjet-commons/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..934ebc5fae39eea90a1c0ab47f989ee3cc59d6f9
--- /dev/null
+++ b/theodolite-benchmarks/hazelcastjet-commons/build.gradle
@@ -0,0 +1,23 @@
+plugins {
+    id 'theodolite.java-commons'
+}
+
+repositories {
+  mavenCentral()
+  maven {
+    url "https://oss.sonatype.org/content/repositories/snapshots/"
+  }
+  maven {
+      url 'https://packages.confluent.io/maven/'
+  }
+}
+
+dependencies {
+    implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true }
+    implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true }
+    implementation 'com.hazelcast.jet:hazelcast-jet:4.5'
+    implementation 'com.hazelcast.jet:hazelcast-jet-kafka:4.5'
+    implementation 'com.hazelcast:hazelcast-kubernetes:2.2.2'
+    implementation 'io.confluent:kafka-avro-serializer:5.3.0'
+    implementation 'org.slf4j:slf4j-api:1.7.25'
+}
\ No newline at end of file
diff --git a/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/BenchmarkConfigBuilder.java b/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/BenchmarkConfigBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..46dd56a8669cce4d29e8dace1bd6c2649a71e1f0
--- /dev/null
+++ b/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/BenchmarkConfigBuilder.java
@@ -0,0 +1,71 @@
+package rocks.theodolite.benchmarks.commons.hazelcastjet;
+
+import com.hazelcast.config.Config;
+import com.hazelcast.config.JoinConfig;
+import org.slf4j.Logger;
+
+/**
+ * Build a Config Object for Benchmarks implemented in Hazelcast Jet.
+ *
+ */
+public class BenchmarkConfigBuilder {
+
+  /**
+   * Builds a Config Object for Benchmarks implemented in Hazelcast Jet using data from the
+   * environment.
+   */
+  public Config buildFromEnv(final Logger logger, final String bootstrapServerDefault,
+      final String hzKubernetesServiceDnsKey) {
+
+    final String bootstrapServer = System.getenv(ConfigurationKeys.BOOTSTRAP_SERVER);
+    final String kubernetesDnsName = System.getenv(ConfigurationKeys.KUBERNETES_DNS_NAME);
+
+    ClusterConfig clusterConfig;
+    if (bootstrapServer != null) { // NOPMD
+      clusterConfig = ClusterConfig.fromBootstrapServer(bootstrapServer);
+      logger.info("Use bootstrap server '{}'.", bootstrapServer);
+    } else if (kubernetesDnsName != null) { // NOPMD
+      clusterConfig = ClusterConfig.fromKubernetesDnsName(kubernetesDnsName);
+      logger.info("Use Kubernetes DNS name '{}'.", kubernetesDnsName);
+    } else {
+      clusterConfig = ClusterConfig.fromBootstrapServer(bootstrapServerDefault);
+      logger.info(
+          "Neither a bootstrap server nor a Kubernetes DNS name was provided. Use default bootstrap server '{}'.", // NOCS
+          bootstrapServerDefault);
+    }
+
+    final String port = System.getenv(ConfigurationKeys.PORT);
+    if (port != null) {
+      clusterConfig.setPort(Integer.parseInt(port));
+    }
+
+    final String portAutoIncrement = System.getenv(ConfigurationKeys.PORT_AUTO_INCREMENT);
+    if (portAutoIncrement != null) {
+      clusterConfig.setPortAutoIncrement(Boolean.parseBoolean(portAutoIncrement));
+    }
+
+    final String clusterNamePrefix = System.getenv(ConfigurationKeys.CLUSTER_NAME_PREFIX);
+    if (clusterNamePrefix != null) {
+      clusterConfig.setClusterNamePrefix(clusterNamePrefix);
+    }
+
+    // Set network config for this hazelcast jet instance
+    final Config config = new Config()
+        .setClusterName(clusterConfig.getClusterNamePrefix());
+    final JoinConfig joinConfig = config.getNetworkConfig()
+        .setPort(clusterConfig.getPort())
+        .setPortAutoIncrement(clusterConfig.isPortAutoIncrement())
+        .getJoin();
+    joinConfig.getMulticastConfig().setEnabled(false);
+    if (clusterConfig.hasBootstrapServer()) {
+      joinConfig.getTcpIpConfig().addMember(clusterConfig.getBootstrapServer());
+    } else if (clusterConfig.hasKubernetesDnsName()) {
+      joinConfig.getKubernetesConfig()
+          .setEnabled(true)
+          .setProperty(hzKubernetesServiceDnsKey, clusterConfig.getKubernetesDnsName());
+    }
+
+    return config;
+  }
+
+}
diff --git a/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/ClusterConfig.java b/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/ClusterConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5a2141799eb97dbedc5fc82fa456b2efee3a813
--- /dev/null
+++ b/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/ClusterConfig.java
@@ -0,0 +1,76 @@
+package rocks.theodolite.benchmarks.commons.hazelcastjet;
+
+/**
+ * Configuration of a load generator cluster.
+ */
+public final class ClusterConfig {
+
+  private static final int PORT_DEFAULT = 5701;
+  private static final String CLUSTER_NAME_PREFIX_DEFAULT = "theodolite-hazelcastjet";
+
+  private final String bootstrapServer;
+  private final String kubernetesDnsName;
+  private int port = PORT_DEFAULT;
+  private boolean portAutoIncrement = true;
+  private String clusterNamePrefix = CLUSTER_NAME_PREFIX_DEFAULT;
+
+  /**
+   * Create a new {@link ClusterConfig} with the given parameter values.
+   */
+  private ClusterConfig(final String bootstrapServer, final String kubernetesDnsName) {
+    this.bootstrapServer = bootstrapServer;
+    this.kubernetesDnsName = kubernetesDnsName;
+  }
+
+  public boolean hasBootstrapServer() {
+    return this.bootstrapServer != null;
+  }
+
+  public String getBootstrapServer() {
+    return this.bootstrapServer;
+  }
+
+  public boolean hasKubernetesDnsName() {
+    return this.kubernetesDnsName != null;
+  }
+
+  public String getKubernetesDnsName() {
+    return this.kubernetesDnsName;
+  }
+
+  public int getPort() {
+    return this.port;
+  }
+
+  public boolean isPortAutoIncrement() {
+    return this.portAutoIncrement;
+  }
+
+  public ClusterConfig setPortAutoIncrement(final boolean portAutoIncrement) { // NOPMD
+    this.portAutoIncrement = portAutoIncrement;
+    return this;
+  }
+
+  public ClusterConfig setPort(final int port) { // NOPMD
+    this.port = port;
+    return this;
+  }
+
+  public String getClusterNamePrefix() {
+    return this.clusterNamePrefix;
+  }
+
+  public ClusterConfig setClusterNamePrefix(final String clusterNamePrefix) { // NOPMD
+    this.clusterNamePrefix = clusterNamePrefix;
+    return this;
+  }
+
+  public static ClusterConfig fromBootstrapServer(final String bootstrapServer) {
+    return new ClusterConfig(bootstrapServer, null);
+  }
+
+  public static ClusterConfig fromKubernetesDnsName(final String kubernetesDnsName) {
+    return new ClusterConfig(null, kubernetesDnsName);
+  }
+
+}
diff --git a/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/ConfigurationKeys.java b/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/ConfigurationKeys.java
new file mode 100644
index 0000000000000000000000000000000000000000..d1705888430c92ee0cec50ea06871746bbe06cb5
--- /dev/null
+++ b/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/ConfigurationKeys.java
@@ -0,0 +1,33 @@
+package rocks.theodolite.benchmarks.commons.hazelcastjet;
+
+/**
+ * Configuration Keys used for Hazelcast Jet Benchmark implementations.
+ */
+public class ConfigurationKeys {
+
+  // Common Keys
+  public static final String BOOTSTRAP_SERVER = "BOOTSTRAP_SERVER";
+  public static final String KUBERNETES_DNS_NAME = "KUBERNETES_DNS_NAME";
+  public static final String PORT = "PORT";
+  public static final String PORT_AUTO_INCREMENT = "PORT_AUTO_INCREMENT";
+  public static final String CLUSTER_NAME_PREFIX = "CLUSTER_NAME_PREFIX";
+  public static final String KAFKA_BOOTSTRAP_SERVERS = "KAFKA_BOOTSTRAP_SERVERS";
+  public static final String SCHEMA_REGISTRY_URL = "SCHEMA_REGISTRY_URL";
+  public static final String KAFKA_INPUT_TOPIC = "KAFKA_INPUT_TOPIC";
+
+  // Additional topics
+  public static final String KAFKA_OUTPUT_TOPIC = "KAFKA_OUTPUT_TOPIC";
+
+  // UC2
+  public static final String DOWNSAMPLE_INTERVAL = "DOWNSAMPLE_INTERVAL";
+
+  // UC3
+  public static final String WINDOW_SIZE_IN_SECONDS = "WINDOW_SIZE_IN_SECONDS";
+  public static final String HOPPING_SIZE_IN_SECONDS = "HOPPING_SIZE_IN_SECONDS";
+
+  // UC4
+  public static final String KAFKA_CONFIGURATION_TOPIC = "KAFKA_CONFIGURATION_TOPIC";
+  public static final String KAFKA_FEEDBACK_TOPIC = "KAFKA_FEEDBACK_TOPIC";
+  public static final String WINDOW_SIZE_UC4 = "WINDOW_SIZE";
+  
+}
diff --git a/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/JetInstanceBuilder.java b/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/JetInstanceBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc2ee052d5e2ed7e7b372baf7b59f24ef3e26e8f
--- /dev/null
+++ b/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/JetInstanceBuilder.java
@@ -0,0 +1,61 @@
+package rocks.theodolite.benchmarks.commons.hazelcastjet;
+
+import com.hazelcast.config.Config;
+import com.hazelcast.jet.Jet;
+import com.hazelcast.jet.JetInstance;
+import org.slf4j.Logger;
+
+/**
+ * Builds JetInstances for Benchmark Implementations in Hazelcast Jet.
+ */
+public class JetInstanceBuilder {
+
+  private Config config;
+
+  /**
+   * Set Hazelcast Config for the JetInstance to be built.
+   *
+   * @param hazelcastConfig Config for this JetInstance to be built.
+   * @return A Uc1JetInstanceBuilder with a set Config.
+   */
+  public JetInstanceBuilder setCustomConfig(final Config hazelcastConfig) { // NOPMD
+    this.config = hazelcastConfig;
+    return this;
+  }
+
+  /**
+   * Sets the ClusterConfig for this builder using the clusterConfigBuilder and environment
+   * variables.
+   *
+   * @param logger A specified logger to log procedures
+   * @param bootstrapServerDefault The default bootstrap server used in case no definition by the
+   *        environment is provided.
+   * @return The Uc1HazelcastJetBuilder factory with a set ClusterConfig.
+   */
+  public JetInstanceBuilder setConfigFromEnv(final Logger logger, // NOPMD
+      final String bootstrapServerDefault, final String hzKubernetesServiceDnsKey) {
+    // Use ClusterConfigBuilder to build a cluster config for this microservice
+    final BenchmarkConfigBuilder configBuilder = new BenchmarkConfigBuilder();
+    this.config =
+        configBuilder.buildFromEnv(logger, bootstrapServerDefault, hzKubernetesServiceDnsKey);
+    return this;
+  }
+
+  /**
+   * Builds and returns a JetInstance. If a config is set, the JetInstance will contain the set
+   * config.
+   *
+   * @return JetInstance
+   */
+  public JetInstance build() {
+    final JetInstance jet = Jet.newJetInstance();
+    if (this.config == null) {
+      return jet;
+    } else {
+      jet.getConfig().setHazelcastConfig(this.config);
+      return jet;
+    }
+
+  }
+
+}
diff --git a/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/KafkaPropertiesBuilder.java b/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/KafkaPropertiesBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..9bce60f57a6ecb9da4578e08d8f49bbb34af934a
--- /dev/null
+++ b/theodolite-benchmarks/hazelcastjet-commons/src/main/java/rocks/theodolite/benchmarks/commons/hazelcastjet/KafkaPropertiesBuilder.java
@@ -0,0 +1,99 @@
+package rocks.theodolite.benchmarks.commons.hazelcastjet;
+
+import io.confluent.kafka.serializers.AbstractKafkaAvroSerDeConfig;
+import io.confluent.kafka.serializers.KafkaAvroDeserializerConfig;
+import java.util.Objects;
+import java.util.Properties;
+import org.apache.kafka.clients.consumer.ConsumerConfig;
+import org.apache.kafka.clients.producer.ProducerConfig;
+
+
+/**
+ * Generalized builder for Kafka properties.
+ * Will always set AUTO_OFFSET_RESET_CONFIG to earliest
+ *
+ */
+public class KafkaPropertiesBuilder {
+
+  private static final String TRUE = "true";
+  private static final String AUTO_OFFSET_RESET_CONFIG = "earliest";
+
+
+  /**
+   * Builds Kafka Properties used for the UC4 Benchmark pipeline.
+   *
+   * @param kafkaBootstrapServerDefault Default bootstrap server if not set by environment.
+   * @param schemaRegistryUrlDefault Default schema registry URL if not set by environment.
+   * @param applicationName Used to set the group id to commit the offsets
+   * @param keyDeserializer Classname for the key deserializer.
+   * @param valueDeserializer Classname for the value deserializer.
+   * @return A Kafka Properties Object containing the values needed for a Pipeline.
+   */
+  public Properties buildKafkaInputReadPropsFromEnv(final String kafkaBootstrapServerDefault,//NOPMD
+                                                    final String schemaRegistryUrlDefault,
+                                                    final String applicationName,
+                                                    final String keyDeserializer,
+                                                    final String valueDeserializer) {
+
+    final String kafkaBootstrapServers = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_BOOTSTRAP_SERVERS),
+        kafkaBootstrapServerDefault);
+    final String schemaRegistryUrl = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.SCHEMA_REGISTRY_URL),
+        schemaRegistryUrlDefault);
+
+    final Properties props = new Properties();
+    props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaBootstrapServers);
+    props.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
+        keyDeserializer);
+    props.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
+        valueDeserializer);
+    props.setProperty(AbstractKafkaAvroSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG, schemaRegistryUrl);
+    props.setProperty(KafkaAvroDeserializerConfig.SPECIFIC_AVRO_READER_CONFIG, TRUE);
+    props.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, AUTO_OFFSET_RESET_CONFIG);
+
+    props.setProperty(ConsumerConfig.GROUP_ID_CONFIG,applicationName);
+    props.setProperty(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,TRUE);
+
+    return props;
+  }
+
+  /**
+   * Builds Kafka Properties used for the UC4 Benchmark pipeline.
+   *
+   * @param kafkaBootstrapServerDefault Default bootstrap server if not set by environment.
+   * @param schemaRegistryUrlDefault Default schema registry URL if not set by environment.
+   * @param keySerializer Classname for the key serializer.
+   * @param valueSerializer Classname for the value serializer.
+   * @return A Kafka Properties Object containing the values needed for a Hazelcast Jet UC4
+   *         Pipeline.
+   */
+  public Properties buildKafkaWritePropsFromEnv(final String kafkaBootstrapServerDefault,//NOPMD
+                                                final String schemaRegistryUrlDefault,
+                                                final String keySerializer,
+                                                final String valueSerializer) {
+
+    final String kafkaBootstrapServers = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_BOOTSTRAP_SERVERS),
+        kafkaBootstrapServerDefault);
+    final String schemaRegistryUrl = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.SCHEMA_REGISTRY_URL),
+        schemaRegistryUrlDefault);
+
+    final Properties props = new Properties();
+    props.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaBootstrapServers);
+    props.setProperty(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
+        keySerializer);
+    props.setProperty(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
+        valueSerializer);
+    props.setProperty(AbstractKafkaAvroSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG, schemaRegistryUrl);
+    props.setProperty("specific.avro.writer", TRUE);
+
+    return props;
+  }
+
+
+
+
+
+}
diff --git a/theodolite-benchmarks/http-bridge/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/http-bridge/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..a375cb792eeb842ecfd1f789fbf6a716df43e9c8
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,127 @@
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.correct_indentation=true
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=true
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.correct_indentation=true
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=true
+sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
diff --git a/theodolite-benchmarks/http-bridge/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/http-bridge/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..87860c815222845c1d264d7d0ce498d3397f8280
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=true
diff --git a/theodolite-benchmarks/http-bridge/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/http-bridge/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..efbcb8c9e5d449194a48ca1ea42b7d807b573db9
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=true
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/http-bridge/Dockerfile b/theodolite-benchmarks/http-bridge/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..b31dbcdef48f3b9eadf81a35c95e441c4b54955b
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/Dockerfile
@@ -0,0 +1,6 @@
+FROM openjdk:11-slim
+
+ADD build/distributions/http-bridge.tar /
+
+CMD  JAVA_OPTS="$JAVA_OPTS -Dorg.slf4j.simpleLogger.defaultLogLevel=$LOG_LEVEL" \
+     /http-bridge/bin/http-bridge
\ No newline at end of file
diff --git a/theodolite-benchmarks/http-bridge/build.gradle b/theodolite-benchmarks/http-bridge/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..fa98d9fdd602174a945df95321f5e32b8c64052f
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/build.gradle
@@ -0,0 +1,36 @@
+plugins {
+  // common java conventions
+  id 'theodolite.java-conventions'
+
+  // make executable
+  id 'application'
+}
+
+repositories {
+  mavenCentral()
+  maven {
+    url "https://oss.sonatype.org/content/repositories/snapshots/"
+  }
+  maven {
+      url 'https://packages.confluent.io/maven/'
+  }
+}
+
+dependencies {
+  implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true }
+  implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true }
+  implementation project(':load-generator-commons')
+  
+  implementation 'io.javalin:javalin:4.3.0'
+  implementation 'io.micrometer:micrometer-core:1.8.3'
+  implementation 'io.micrometer:micrometer-registry-prometheus:1.8.3'
+  implementation 'com.google.code.gson:gson:2.8.2'
+  runtimeOnly 'org.slf4j:slf4j-simple:1.7.25'
+
+  testImplementation 'junit:junit:4.12'
+}
+
+
+tasks.distZip.enabled = false
+
+mainClassName = "rocks.theodolite.benchmarks.httpbridge.HttpBridge"
diff --git a/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/Deserializer.java b/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/Deserializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..80f325691b326a88e5a5033c526c575455bd2cd1
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/Deserializer.java
@@ -0,0 +1,13 @@
+package rocks.theodolite.benchmarks.httpbridge;
+
+/**
+ * A class for converting objects to strings.
+ *
+ * @param <T> Type to be deserialized from.
+ */
+@FunctionalInterface
+public interface Deserializer<T> {
+
+  T deserialize(String json);
+
+}
diff --git a/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/Endpoint.java b/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/Endpoint.java
new file mode 100644
index 0000000000000000000000000000000000000000..ac83574adb74c8d9320ab858673ea009bd3296a1
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/Endpoint.java
@@ -0,0 +1,52 @@
+package rocks.theodolite.benchmarks.httpbridge;
+
+import rocks.theodolite.benchmarks.loadgenerator.RecordSender;
+
+/**
+ * Class describing an endpoint of the {@link HttpBridge}, which converts JSON objects to Java
+ * objects and sends them using a {@link RecordSender}.
+ *
+ * @param <T> Type of objects this endpoint receives and converts.
+ */
+public class Endpoint<T> {
+
+  private final String path;
+
+  private final Deserializer<? extends T> recordDeserializer;
+
+  private final RecordSender<? super T> recordSender;
+
+  /**
+   * Create a new {@link Endpoint} at the given path.
+   */
+  public Endpoint(
+      final String path,
+      final Deserializer<? extends T> recordDeserializer,
+      final RecordSender<? super T> recordSender) {
+    this.path = path;
+    this.recordDeserializer = recordDeserializer;
+    this.recordSender = recordSender;
+  }
+
+  /**
+   * Create a new {@link Endpoint} at the given path with a {@link GsonDeserializer}.
+   */
+  public Endpoint(
+      final String path,
+      final Class<T> recordType,
+      final RecordSender<? super T> recordSender) {
+    this.path = path;
+    this.recordDeserializer = new GsonDeserializer<>(recordType);
+    this.recordSender = recordSender;
+  }
+
+  public String getPath() {
+    return this.path;
+  }
+
+  public void convert(final String json) {
+    final T record = this.recordDeserializer.deserialize(json);
+    this.recordSender.send(record);
+  }
+
+}
diff --git a/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/EnvVarHttpBridgeFactory.java b/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/EnvVarHttpBridgeFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..d3c172ac87221ab03f0171883df26802bf5a3aa9
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/EnvVarHttpBridgeFactory.java
@@ -0,0 +1,59 @@
+package rocks.theodolite.benchmarks.httpbridge;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import rocks.theodolite.benchmarks.loadgenerator.ConfigurationKeys;
+import rocks.theodolite.benchmarks.loadgenerator.TitanKafkaSenderFactory;
+import titan.ccp.model.records.ActivePowerRecord;
+
+class EnvVarHttpBridgeFactory {
+
+  private static final String PORT_KEY = "PORT";
+  private static final int PORT_DEFAULT = 8080;
+
+  private static final String HOST_KEY = "HOST";
+  private static final String HOST_DEFAULT = "0.0.0.0"; // NOPMD
+
+  private static final String KAFKA_BOOTSTRAP_SERVERS_DEFAULT = "localhost:9092"; // NOPMD
+  private static final String KAFKA_TOPIC_DEFAULT = "input";
+  private static final String SCHEMA_REGISTRY_URL_DEFAULT = "http://localhost:8081";
+
+  public HttpBridge create() {
+    final Endpoint<?> converter = new Endpoint<>(
+        "/",
+        ActivePowerRecord.class,
+        TitanKafkaSenderFactory.forKafkaConfig(
+            this.getKafkaBootstrapServer(),
+            this.getKafkaTopic(),
+            this.getSchemaRegistryUrl()));
+    return new HttpBridge(this.getHost(), this.getPort(), List.of(converter));
+  }
+
+  private String getHost() {
+    return Objects.requireNonNullElse(System.getenv(HOST_KEY), HOST_DEFAULT);
+  }
+
+  private int getPort() {
+    return Optional.ofNullable(System.getenv(PORT_KEY)).map(Integer::parseInt).orElse(PORT_DEFAULT);
+  }
+
+  private String getKafkaBootstrapServer() {
+    return Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_BOOTSTRAP_SERVERS),
+        KAFKA_BOOTSTRAP_SERVERS_DEFAULT);
+  }
+
+  private String getKafkaTopic() {
+    return Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_INPUT_TOPIC),
+        KAFKA_TOPIC_DEFAULT);
+  }
+
+  private String getSchemaRegistryUrl() {
+    return Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.SCHEMA_REGISTRY_URL),
+        SCHEMA_REGISTRY_URL_DEFAULT);
+  }
+
+}
diff --git a/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/GsonDeserializer.java b/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/GsonDeserializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..947e78947c8b381752648ecb53c90dc67da31c7b
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/GsonDeserializer.java
@@ -0,0 +1,29 @@
+package rocks.theodolite.benchmarks.httpbridge;
+
+import com.google.gson.Gson;
+
+/**
+ * A {@link Deserializer} based on GSON.
+ *
+ * @param <T> Type to be serialized from.
+ */
+public class GsonDeserializer<T> implements Deserializer<T> {
+
+  private final Gson gson;
+  private final Class<T> targetClass;
+
+  public GsonDeserializer(final Class<T> targetClass) {
+    this(new Gson(), targetClass);
+  }
+
+  public GsonDeserializer(final Gson gson, final Class<T> targetClass) {
+    this.gson = gson;
+    this.targetClass = targetClass;
+  }
+
+  @Override
+  public T deserialize(final String json) {
+    return this.gson.fromJson(json, this.targetClass);
+  }
+
+}
diff --git a/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/HttpBridge.java b/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/HttpBridge.java
new file mode 100644
index 0000000000000000000000000000000000000000..3de0bc5947e7b2b38c6cbb4c6527a3532feee28e
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/HttpBridge.java
@@ -0,0 +1,40 @@
+package rocks.theodolite.benchmarks.httpbridge;
+
+import java.util.List;
+import rocks.theodolite.benchmarks.loadgenerator.RecordSender;
+
+/**
+ * Class that creates a webserver with potentially multiple {@link Endpoint}s, which receives JSON
+ * objects at these endpoints, converts them to Java objects and send them using
+ * {@link RecordSender}s.
+ */
+public class HttpBridge {
+
+  private final JavalinWebServer webServer;
+
+  public HttpBridge(final String host, final int port, final List<Endpoint<?>> converters) {
+    this.webServer = new JavalinWebServer(converters, host, port);
+  }
+
+  public void start() {
+    this.webServer.start();
+  }
+
+  public void stop() {
+    this.webServer.stop();
+  }
+
+  public void runAsStandalone() {
+    Runtime.getRuntime().addShutdownHook(new Thread(() -> this.stop()));
+    this.start();
+  }
+
+  public static HttpBridge fromEnvironment() {
+    return new EnvVarHttpBridgeFactory().create();
+  }
+
+  public static void main(final String[] args) {
+    HttpBridge.fromEnvironment().runAsStandalone();
+  }
+
+}
diff --git a/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/JavalinWebServer.java b/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/JavalinWebServer.java
new file mode 100644
index 0000000000000000000000000000000000000000..a7c0ee75943c0255432013c3e6cc73c2dde2f3ec
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/JavalinWebServer.java
@@ -0,0 +1,66 @@
+package rocks.theodolite.benchmarks.httpbridge;
+
+import io.javalin.Javalin;
+import io.javalin.plugin.metrics.MicrometerPlugin;
+import io.micrometer.prometheus.PrometheusConfig;
+import io.micrometer.prometheus.PrometheusMeterRegistry;
+import io.prometheus.client.exporter.common.TextFormat;
+import java.util.Collection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of a webserver based on the Javalin framework.
+ */
+public class JavalinWebServer {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(JavalinWebServer.class);
+
+  private static final int HTTP_SUCCESS = 200;
+
+  private final Javalin app;
+
+  private final PrometheusMeterRegistry registry;
+
+  private final String host;
+  private final int port;
+
+  /**
+   * Create a new instance, running on the specified host and port with the configured endpoints.
+   */
+  public JavalinWebServer(
+      final Collection<Endpoint<?>> converters,
+      final String host,
+      final int port) {
+    this.host = host;
+    this.port = port;
+    this.registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
+    this.app = Javalin.create(config -> {
+      config.registerPlugin(new MicrometerPlugin(this.registry));
+    });
+    this.configureRoutes(converters);
+  }
+
+  private void configureRoutes(final Collection<Endpoint<?>> endpoints) {
+    for (final Endpoint<?> endpoint : endpoints) {
+      this.app.post(endpoint.getPath(), ctx -> {
+        final String record = ctx.body();
+        LOGGER.debug("Received record at '{}': {}", ctx.path(), record);
+        endpoint.convert(record);
+        ctx.status(HTTP_SUCCESS);
+      });
+    }
+    this.app.get("/metrics", ctx -> ctx
+        .contentType(TextFormat.CONTENT_TYPE_004)
+        .result(this.registry.scrape()));
+  }
+
+  public void start() {
+    this.app.start(this.host, this.port);
+  }
+
+  public void stop() {
+    this.app.close();
+  }
+
+}
diff --git a/theodolite-benchmarks/kstreams-commons/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/kstreams-commons/.settings/org.eclipse.jdt.ui.prefs
index 98b5ca8064a352aacfe2aebd13fbd0a87735fc3e..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/kstreams-commons/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/kstreams-commons/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,32 +12,80 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
-cleanup.remove_redundant_semicolons=false
+cleanup.remove_redundant_semicolons=true
 cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,27 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -79,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
 sp_cleanup.remove_redundant_semicolons=false
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -114,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/kstreams-commons/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/kstreams-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/kstreams-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/kstreams-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/kstreams-commons/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/kstreams-commons/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/kstreams-commons/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/kstreams-commons/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/kstreams-commons/build.gradle b/theodolite-benchmarks/kstreams-commons/build.gradle
index 7683ffe39314ec375eda0ed4e139d618d44a7328..167a75327b251af20b1142fe42c82b3bbedfe62b 100644
--- a/theodolite-benchmarks/kstreams-commons/build.gradle
+++ b/theodolite-benchmarks/kstreams-commons/build.gradle
@@ -17,7 +17,7 @@ dependencies {
   // implementation 'org.slf4j:slf4j-simple:1.7.25'
   implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true }
   implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true }
-  implementation 'org.apache.kafka:kafka-streams:2.6.0'
+  implementation 'org.apache.kafka:kafka-streams:3.1.0'
 
   // Use JUnit test framework
   testImplementation 'junit:junit:4.12'
diff --git a/theodolite-benchmarks/kstreams-commons/src/main/java/theodolite/commons/kafkastreams/ConfigurationKeys.java b/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/ConfigurationKeys.java
similarity index 95%
rename from theodolite-benchmarks/kstreams-commons/src/main/java/theodolite/commons/kafkastreams/ConfigurationKeys.java
rename to theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/ConfigurationKeys.java
index ca1838b84a4f1b3ddf11ad4dea8e34792371974b..ca74aa7d9fd88a7d3c20589438e0c9454062d2f0 100644
--- a/theodolite-benchmarks/kstreams-commons/src/main/java/theodolite/commons/kafkastreams/ConfigurationKeys.java
+++ b/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/ConfigurationKeys.java
@@ -1,4 +1,4 @@
-package theodolite.commons.kafkastreams;
+package rocks.theodolite.benchmarks.commons.kstreams;
 
 /**
  * Keys to access configuration parameters.
diff --git a/theodolite-benchmarks/kstreams-commons/src/main/java/theodolite/commons/kafkastreams/KafkaStreamsBuilder.java b/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/KafkaStreamsBuilder.java
similarity index 83%
rename from theodolite-benchmarks/kstreams-commons/src/main/java/theodolite/commons/kafkastreams/KafkaStreamsBuilder.java
rename to theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/KafkaStreamsBuilder.java
index 89bd3147f0d3bb7a5fecc5d8c7d277bd294494ad..06e8591eebc538fcfaed2db394625d8a6dd8b033 100644
--- a/theodolite-benchmarks/kstreams-commons/src/main/java/theodolite/commons/kafkastreams/KafkaStreamsBuilder.java
+++ b/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/KafkaStreamsBuilder.java
@@ -1,4 +1,4 @@
-package theodolite.commons.kafkastreams;
+package rocks.theodolite.benchmarks.commons.kstreams;
 
 import java.util.Properties;
 import java.util.function.Function;
@@ -70,18 +70,15 @@ public abstract class KafkaStreamsBuilder {
 
     // optional configurations
     this.setOptionalProperty(propBuilder, StreamsConfig.ACCEPTABLE_RECOVERY_LAG_CONFIG,
-        this.config::getLong,
-        p -> p >= 0);
+        this.config::getLong, p -> p >= 0);
     this.setOptionalProperty(propBuilder, StreamsConfig.BUFFERED_RECORDS_PER_PARTITION_CONFIG,
         this.config::getInt, p -> p > 0);
     this.setOptionalProperty(propBuilder, StreamsConfig.CACHE_MAX_BYTES_BUFFERING_CONFIG,
-        this.config::getInt,
-        p -> p >= 0);
+        this.config::getInt, p -> p >= 0);
     this.setOptionalProperty(propBuilder, StreamsConfig.COMMIT_INTERVAL_MS_CONFIG,
         this.config::getInt, p -> p >= 0);
     this.setOptionalProperty(propBuilder, StreamsConfig.MAX_TASK_IDLE_MS_CONFIG,
-        this.config::getLong,
-        p -> p >= 0);
+        this.config::getLong, p -> p >= 0);
     this.setOptionalProperty(propBuilder, StreamsConfig.MAX_WARMUP_REPLICAS_CONFIG,
         this.config::getInt, p -> p >= 1);
     this.setOptionalProperty(propBuilder, StreamsConfig.NUM_STANDBY_REPLICAS_CONFIG,
@@ -89,22 +86,28 @@ public abstract class KafkaStreamsBuilder {
     this.setOptionalProperty(propBuilder, StreamsConfig.NUM_STREAM_THREADS_CONFIG,
         this.config::getInt, p -> p > 0);
     this.setOptionalProperty(propBuilder, StreamsConfig.POLL_MS_CONFIG,
-        this.config::getLong,
-        p -> p >= 0);
+        this.config::getLong, p -> p >= 0);
     this.setOptionalProperty(propBuilder, StreamsConfig.PROCESSING_GUARANTEE_CONFIG,
-        this.config::getString, p -> StreamsConfig.AT_LEAST_ONCE.equals(p)
-            || StreamsConfig.EXACTLY_ONCE.equals(p) || StreamsConfig.EXACTLY_ONCE_BETA.equals(p));
+        this.config::getString, this::validateProcessingGuarantee);
     this.setOptionalProperty(propBuilder, StreamsConfig.REPLICATION_FACTOR_CONFIG,
         this.config::getInt, p -> p >= 0);
 
-    if (this.config.containsKey(StreamsConfig.TOPOLOGY_OPTIMIZATION)
-        && this.config.getBoolean(StreamsConfig.TOPOLOGY_OPTIMIZATION)) {
-      propBuilder.set(StreamsConfig.TOPOLOGY_OPTIMIZATION, StreamsConfig.OPTIMIZE);
+    if (this.config.containsKey(StreamsConfig.TOPOLOGY_OPTIMIZATION_CONFIG)
+        && this.config.getBoolean(StreamsConfig.TOPOLOGY_OPTIMIZATION_CONFIG)) {
+      propBuilder.set(StreamsConfig.TOPOLOGY_OPTIMIZATION_CONFIG, StreamsConfig.OPTIMIZE);
     }
 
     return propBuilder.build();
   }
 
+  @SuppressWarnings("deprecation")
+  private boolean validateProcessingGuarantee(final String processingGuarantee) {
+    return StreamsConfig.AT_LEAST_ONCE.equals(processingGuarantee)
+        // We continue support EXACTLY_ONCE to allow benchmarking it against v2
+        || StreamsConfig.EXACTLY_ONCE.equals(processingGuarantee)
+        || StreamsConfig.EXACTLY_ONCE_V2.equals(processingGuarantee);
+  }
+
   /**
    * Method to implement a {@link Topology} for a {@code KafkaStreams} application.
    *
@@ -116,7 +119,7 @@ public abstract class KafkaStreamsBuilder {
    * Builds the {@link KafkaStreams} instance.
    */
   public KafkaStreams build() {
-    // Create the Kafka streams instance.
+    // Create the Kafka Streams instance.
     final Properties properties = this.buildProperties();
     return new KafkaStreams(this.buildTopology(properties), properties);
   }
diff --git a/theodolite-benchmarks/load-generator-commons/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/load-generator-commons/.settings/org.eclipse.jdt.ui.prefs
index fa98ca63d77bdee891150bd6713f70197a75cefc..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/load-generator-commons/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/load-generator-commons/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,25 +12,72 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
 cleanup.remove_redundant_semicolons=true
@@ -37,6 +85,7 @@ cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,27 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -79,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -114,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/load-generator-commons/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/load-generator-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/load-generator-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/load-generator-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/load-generator-commons/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/load-generator-commons/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/load-generator-commons/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/load-generator-commons/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/load-generator-commons/build.gradle b/theodolite-benchmarks/load-generator-commons/build.gradle
index 2d8f77b5154b5b788e0729da69122b443740ce75..62542eeabc1cccb35fa9f71d1929b72956a56999 100644
--- a/theodolite-benchmarks/load-generator-commons/build.gradle
+++ b/theodolite-benchmarks/load-generator-commons/build.gradle
@@ -21,6 +21,9 @@ dependencies {
   implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true }
   implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true }
   implementation 'org.apache.kafka:kafka-streams:2.6.0' // TODO required?
+  implementation platform('com.google.cloud:libraries-bom:24.2.0')
+  implementation 'com.google.protobuf:protobuf-java-util'
+  implementation 'com.google.cloud:google-cloud-pubsub'
 
   // Use JUnit test framework
   testImplementation 'junit:junit:4.12'
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/BeforeAction.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/BeforeAction.java
similarity index 82%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/BeforeAction.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/BeforeAction.java
index 56af95d70f762095a6fe090457b7d4b473a43b1a..852d5da827fe5d13572a4e44046a96924badda4e 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/BeforeAction.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/BeforeAction.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 /**
  * Describes the before action which is executed before every sub experiment.
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/ClusterConfig.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/ClusterConfig.java
similarity index 97%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/ClusterConfig.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/ClusterConfig.java
index 9d84dc67461f98fabdee4c8e0784ad7394d7f108..ae8778db3011b474daf1aff05a0c393ee0febb31 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/ClusterConfig.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/ClusterConfig.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 /**
  * Configuration of a load generator cluster.
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/ConfigurationKeys.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/ConfigurationKeys.java
similarity index 72%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/ConfigurationKeys.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/ConfigurationKeys.java
index 7a60e271f04e396b2e0c69b1fcfee1d8a1ca8a7d..eb80d25eb327f2e3dc10dc2977131ac7edfef69d 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/ConfigurationKeys.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/ConfigurationKeys.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 /**
  * Keys to access configuration parameters.
@@ -23,6 +23,8 @@ public final class ConfigurationKeys {
 
   public static final String THREADS = "THREADS";
 
+  public static final String DISABLE_DNS_CACHING = "DISABLE_DNS_CACHING";
+
   public static final String TARGET = "TARGET";
 
   public static final String KAFKA_BOOTSTRAP_SERVERS = "KAFKA_BOOTSTRAP_SERVERS";
@@ -39,6 +41,17 @@ public final class ConfigurationKeys {
 
   public static final String HTTP_URL = "HTTP_URL";
 
+  public static final String HTTP_ASYNC = "HTTP_ASYNC";
+
+  public static final String HTTP_TIMEOUT_MS = "HTTP_TIMEOUT_MS";
+
+  public static final String PUBSUB_INPUT_TOPIC = "PUBSUB_INPUT_TOPIC";
+
+  public static final String PUBSUB_PROJECT = "PUBSUB_PROJECT";
+
+  public static final String PUBSUB_EMULATOR_HOST = "PUBSUB_EMULATOR_HOST";
+
+
   private ConfigurationKeys() {}
 
 }
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/EnvVarLoadGeneratorFactory.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/EnvVarLoadGeneratorFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae9a6d4220ceaec091a0a2fb49fb82f16fdbb42e
--- /dev/null
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/EnvVarLoadGeneratorFactory.java
@@ -0,0 +1,159 @@
+package rocks.theodolite.benchmarks.loadgenerator;
+
+import java.net.URI;
+import java.time.Duration;
+import java.util.Objects;
+import java.util.Properties;
+import org.apache.kafka.clients.producer.ProducerConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import titan.ccp.model.records.ActivePowerRecord;
+
+class EnvVarLoadGeneratorFactory {
+
+  public static final boolean DISABLE_DNS_CACHING_DEFAULT = false;
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(EnvVarLoadGeneratorFactory.class);
+
+  public LoadGenerator create(final LoadGenerator loadGeneratorTemplate) {
+
+    final boolean disableDnsCaching = Boolean.parseBoolean(Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.DISABLE_DNS_CACHING),
+        Boolean.toString(DISABLE_DNS_CACHING_DEFAULT)));
+    if (disableDnsCaching) {
+      this.disableDnsCaching();
+    }
+
+    final int numSensors = Integer.parseInt(Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.NUM_SENSORS),
+        Integer.toString(LoadGenerator.NUMBER_OF_KEYS_DEFAULT)));
+    final int periodMs = Integer.parseInt(Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.PERIOD_MS),
+        Integer.toString(LoadGenerator.PERIOD_MS_DEFAULT)));
+    final double value = Double.parseDouble(Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.VALUE),
+        Integer.toString(LoadGenerator.VALUE_DEFAULT)));
+    final int threads = Integer.parseInt(Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.THREADS),
+        Integer.toString(LoadGenerator.THREADS_DEFAULT)));
+
+    return loadGeneratorTemplate
+        .setClusterConfig(this.buildClusterConfig())
+        .setLoadDefinition(new WorkloadDefinition(
+            new KeySpace(LoadGenerator.SENSOR_PREFIX_DEFAULT, numSensors),
+            Duration.ofMillis(periodMs)))
+        .setGeneratorConfig(new LoadGeneratorConfig(GeneratorAction.from(
+            TitanRecordGenerator.forConstantValue(value),
+            this.buildRecordSender())))
+        .withThreads(threads);
+  }
+
+  private ClusterConfig buildClusterConfig() {
+    final String bootstrapServer = System.getenv(ConfigurationKeys.BOOTSTRAP_SERVER);
+    final String kubernetesDnsName = System.getenv(ConfigurationKeys.KUBERNETES_DNS_NAME);
+
+    ClusterConfig clusterConfig;
+    if (bootstrapServer != null) { // NOPMD
+      clusterConfig = ClusterConfig.fromBootstrapServer(bootstrapServer);
+      LOGGER.info("Use bootstrap server '{}'.", bootstrapServer);
+    } else if (kubernetesDnsName != null) { // NOPMD
+      clusterConfig = ClusterConfig.fromKubernetesDnsName(kubernetesDnsName);
+      LOGGER.info("Use Kubernetes DNS name '{}'.", kubernetesDnsName);
+    } else {
+      clusterConfig = ClusterConfig.fromBootstrapServer(LoadGenerator.BOOTSTRAP_SERVER_DEFAULT);
+      LOGGER.info(
+          "Neither a bootstrap server nor a Kubernetes DNS name was provided. Use default bootstrap server '{}'.", // NOCS
+          LoadGenerator.BOOTSTRAP_SERVER_DEFAULT);
+    }
+
+    final String port = System.getenv(ConfigurationKeys.PORT);
+    if (port != null) {
+      clusterConfig.setPort(Integer.parseInt(port));
+    }
+
+    final String portAutoIncrement = System.getenv(ConfigurationKeys.PORT_AUTO_INCREMENT);
+    if (portAutoIncrement != null) {
+      clusterConfig.setPortAutoIncrement(Boolean.parseBoolean(portAutoIncrement));
+    }
+
+    final String clusterNamePrefix = System.getenv(ConfigurationKeys.CLUSTER_NAME_PREFIX);
+    if (clusterNamePrefix != null) {
+      clusterConfig.setClusterNamePrefix(portAutoIncrement);
+    }
+
+    return clusterConfig;
+  }
+
+  private RecordSender<ActivePowerRecord> buildRecordSender() {
+    final LoadGeneratorTarget target = LoadGeneratorTarget.from(
+        Objects.requireNonNullElse(System.getenv(ConfigurationKeys.TARGET),
+            LoadGenerator.TARGET_DEFAULT.getValue()));
+
+    final RecordSender<ActivePowerRecord> recordSender; // NOPMD
+    if (target == LoadGeneratorTarget.KAFKA) {
+      final String kafkaBootstrapServers = Objects.requireNonNullElse(
+          System.getenv(ConfigurationKeys.KAFKA_BOOTSTRAP_SERVERS),
+          LoadGenerator.KAFKA_BOOTSTRAP_SERVERS_DEFAULT);
+      final String kafkaInputTopic = Objects.requireNonNullElse(
+          System.getenv(ConfigurationKeys.KAFKA_INPUT_TOPIC),
+          LoadGenerator.KAFKA_TOPIC_DEFAULT);
+      final String schemaRegistryUrl = Objects.requireNonNullElse(
+          System.getenv(ConfigurationKeys.SCHEMA_REGISTRY_URL),
+          LoadGenerator.SCHEMA_REGISTRY_URL_DEFAULT);
+      final Properties kafkaProperties = new Properties();
+      kafkaProperties.compute(ProducerConfig.BATCH_SIZE_CONFIG,
+          (k, v) -> System.getenv(ConfigurationKeys.KAFKA_BATCH_SIZE));
+      kafkaProperties.compute(ProducerConfig.LINGER_MS_CONFIG,
+          (k, v) -> System.getenv(ConfigurationKeys.KAFKA_LINGER_MS));
+      kafkaProperties.compute(ProducerConfig.BUFFER_MEMORY_CONFIG,
+          (k, v) -> System.getenv(ConfigurationKeys.KAFKA_BUFFER_MEMORY));
+      recordSender = TitanKafkaSenderFactory.forKafkaConfig(
+          kafkaBootstrapServers,
+          kafkaInputTopic,
+          schemaRegistryUrl);
+      LOGGER.info(
+          "Use Kafka as target with bootstrap server '{}', schema registry url '{}' and topic '{}'.", // NOCS
+          kafkaBootstrapServers, schemaRegistryUrl, kafkaInputTopic);
+    } else if (target == LoadGeneratorTarget.HTTP) {
+      final URI url = URI.create(
+          Objects.requireNonNullElse(
+              System.getenv(ConfigurationKeys.HTTP_URL),
+              LoadGenerator.HTTP_URI_DEFAULT));
+      final boolean async = Boolean.parseBoolean(Objects.requireNonNullElse(
+          System.getenv(ConfigurationKeys.HTTP_ASYNC),
+          Boolean.toString(LoadGenerator.HTTP_ASYNC_DEFAULT)));
+      final long timeoutMs = Integer.parseInt(Objects.requireNonNullElse(
+          System.getenv(ConfigurationKeys.HTTP_TIMEOUT_MS),
+          Long.toString(LoadGenerator.HTTP_TIMEOUT_MS_DEFAULT)));
+      recordSender = new HttpRecordSender<>(url, async, Duration.ofMillis(timeoutMs));
+      LOGGER.info("Use HTTP server as target with URL '{}' and asynchronously: '{}'.", url, async);
+    } else if (target == LoadGeneratorTarget.PUBSUB) {
+      final String project = System.getenv(ConfigurationKeys.PUBSUB_PROJECT);
+      final String inputTopic = Objects.requireNonNullElse(
+          System.getenv(ConfigurationKeys.PUBSUB_INPUT_TOPIC),
+          LoadGenerator.PUBSUB_TOPIC_DEFAULT);
+      final String emulatorHost = System.getenv(ConfigurationKeys.PUBSUB_EMULATOR_HOST);
+      if (emulatorHost != null) { // NOPMD
+        LOGGER.info("Use Pub/Sub as target with emulator host {} and topic '{}'.",
+            emulatorHost,
+            inputTopic);
+        recordSender = TitanPubSubSenderFactory.forEmulatedPubSubConfig(emulatorHost, inputTopic);
+      } else if (project != null) { // NOPMD
+        LOGGER.info("Use Pub/Sub as target with project {} and topic '{}'.", project, inputTopic);
+        recordSender = TitanPubSubSenderFactory.forPubSubConfig(project, inputTopic);
+      } else {
+        throw new IllegalStateException("Neither an emulator host nor a project was provided.");
+      }
+    } else {
+      // Should never happen
+      throw new IllegalStateException("Target " + target + " is not handled yet.");
+    }
+    return recordSender;
+  }
+
+  private void disableDnsCaching() {
+    LOGGER.info("Disable DNS caching.");
+    java.security.Security.setProperty("networkaddress.cache.ttl", "0");
+  }
+
+}
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/GeneratorAction.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/GeneratorAction.java
similarity index 60%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/GeneratorAction.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/GeneratorAction.java
index 11a9cbf2d96bc3a02f3972ba23f2167af06a2ec3..fb3bf1c9f802d2af2a0eae72bc58c9e609a6b624 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/GeneratorAction.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/GeneratorAction.java
@@ -1,18 +1,22 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 /**
  * Interface representing a record generator action consisting of generating a record and sending
  * it.
  */
 @FunctionalInterface
-interface GeneratorAction {
+public interface GeneratorAction {
 
   void generate(final String key);
 
+  default void shutdown() {
+    // Nothing to do per default
+  }
+
   public static <T> GeneratorAction from(
       final RecordGenerator<? extends T> generator,
       final RecordSender<? super T> sender) {
-    return key -> sender.send(generator.generate(key));
+    return new GeneratorActionImpl<>(generator, sender);
   }
 
 }
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/GeneratorActionImpl.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/GeneratorActionImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d177b7193ee8df8b4d65546cbbcbb6f49a95488
--- /dev/null
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/GeneratorActionImpl.java
@@ -0,0 +1,27 @@
+package rocks.theodolite.benchmarks.loadgenerator;
+
+class GeneratorActionImpl<T> implements GeneratorAction {
+
+  private final RecordGenerator<? extends T> generator;
+
+  private final RecordSender<? super T> sender;
+
+  public GeneratorActionImpl(
+      final RecordGenerator<? extends T> generator,
+      final RecordSender<? super T> sender) {
+    this.generator = generator;
+    this.sender = sender;
+  }
+
+  @Override
+  public void shutdown() {
+    this.generator.close();
+    this.sender.close();
+  }
+
+  @Override
+  public void generate(final String key) {
+    this.sender.send(this.generator.generate(key));
+  }
+
+}
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/HazelcastRunner.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/HazelcastRunner.java
similarity index 84%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/HazelcastRunner.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/HazelcastRunner.java
index c010492950c5caace9ff85baefee1af4e46d25bb..3b222a332fc76159aedcf82a1753363c7b1e414e 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/HazelcastRunner.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/HazelcastRunner.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 import com.hazelcast.cluster.Member;
 import com.hazelcast.cluster.MembershipEvent;
@@ -36,7 +36,7 @@ public class HazelcastRunner {
   }
 
   /**
-   * Start the workload generation and blocks until the workload generation is stopped again.
+   * Start the load generation and blocks until the load generation is stopped again.
    */
   public void runBlocking() {
     while (!this.stopAction.isDone()) {
@@ -52,19 +52,24 @@ public class HazelcastRunner {
   }
 
   public void restart() {
-    this.stopRunnerState();
+    this.stopRunnerStateAsync();
   }
 
+  /**
+   * Stop generating load and clean up the entire state.
+   */
   public void stop() {
     this.stopAction.complete(null);
-    this.stopRunnerState();
+    this.stopRunnerStateAsync().join();
+    this.hzInstance.shutdown();
   }
 
-  private void stopRunnerState() {
+  private CompletableFuture<Void> stopRunnerStateAsync() {
     synchronized (this) {
       if (this.runnerState != null) {
-        this.runnerState.stopAsync();
+        return this.runnerState.stopAsync();
       }
+      return CompletableFuture.completedFuture(null);
     }
   }
 
@@ -94,7 +99,9 @@ public class HazelcastRunner {
         .getJoin();
     joinConfig.getMulticastConfig().setEnabled(false);
     if (cluster.hasBootstrapServer()) {
-      joinConfig.getTcpIpConfig().addMember(cluster.getBootstrapServer());
+      joinConfig.getTcpIpConfig()
+          .setEnabled(true)
+          .addMember(cluster.getBootstrapServer());
     } else if (cluster.hasKubernetesDnsName()) {
       joinConfig.getKubernetesConfig()
           .setEnabled(true)
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/HazelcastRunnerStateInstance.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/HazelcastRunnerStateInstance.java
similarity index 96%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/HazelcastRunnerStateInstance.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/HazelcastRunnerStateInstance.java
index d8fd7de421b88749a2077f81329213ff754e1608..81a6db7329309a8c2b09fb3308cb496c5420a206 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/HazelcastRunnerStateInstance.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/HazelcastRunnerStateInstance.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 import com.google.common.collect.Streams;
 import com.hazelcast.cluster.Member;
@@ -27,6 +27,7 @@ public class HazelcastRunnerStateInstance {
   private static final Duration TASK_ASSIGNMENT_WAIT_DURATION = Duration.ofMillis(500);
 
   private final CompletableFuture<Void> stopAction = new CompletableFuture<>();
+  private final CompletableFuture<Void> stopFinished = new CompletableFuture<>();
   private LoadGeneratorExecution loadGeneratorExecution;
 
   private final LoadGeneratorConfig loadGeneratorConfig;
@@ -61,10 +62,12 @@ public class HazelcastRunnerStateInstance {
     }
     this.stopAction.join();
     this.stopLoadGeneration();
+    this.stopFinished.complete(null);
   }
 
-  public void stopAsync() {
+  public CompletableFuture<Void> stopAsync() {
     this.stopAction.complete(null);
+    return this.stopFinished;
   }
 
   private void tryPerformBeforeAction() {
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/HttpRecordSender.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/HttpRecordSender.java
similarity index 69%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/HttpRecordSender.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/HttpRecordSender.java
index 6b7a5db067c8117f046aa0ff1c6f5d56c35c4321..f740c3696878516f29d0e06ba879cd23010a157b 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/HttpRecordSender.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/HttpRecordSender.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 import com.google.gson.Gson;
 import java.net.URI;
@@ -7,6 +7,7 @@ import java.net.http.HttpRequest;
 import java.net.http.HttpResponse;
 import java.net.http.HttpResponse.BodyHandler;
 import java.net.http.HttpResponse.BodyHandlers;
+import java.time.Duration;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
@@ -23,6 +24,8 @@ public class HttpRecordSender<T extends SpecificRecord> implements RecordSender<
 
   private static final int HTTP_OK = 200;
 
+  private static final Duration DEFAULT_CONNECTION_TIMEOUT = Duration.ofSeconds(1);
+
   private static final Logger LOGGER = LoggerFactory.getLogger(HttpRecordSender.class);
 
   private final Gson gson = new Gson();
@@ -33,6 +36,8 @@ public class HttpRecordSender<T extends SpecificRecord> implements RecordSender<
 
   private final boolean async;
 
+  private final Duration connectionTimeout;
+
   private final List<Integer> validStatusCodes;
 
   /**
@@ -41,7 +46,18 @@ public class HttpRecordSender<T extends SpecificRecord> implements RecordSender<
    * @param uri the {@link URI} records should be sent to
    */
   public HttpRecordSender(final URI uri) {
-    this(uri, true, List.of(HTTP_OK));
+    this(uri, false, DEFAULT_CONNECTION_TIMEOUT);
+  }
+
+  /**
+   * Create a new {@link HttpRecordSender}.
+   *
+   * @param uri the {@link URI} records should be sent to
+   * @param async whether HTTP requests should be sent asynchronous
+   * @param connectionTimeout timeout for the HTTP connection
+   */
+  public HttpRecordSender(final URI uri, final boolean async, final Duration connectionTimeout) {
+    this(uri, async, connectionTimeout, List.of(HTTP_OK));
   }
 
   /**
@@ -49,12 +65,17 @@ public class HttpRecordSender<T extends SpecificRecord> implements RecordSender<
    *
    * @param uri the {@link URI} records should be sent to
    * @param async whether HTTP requests should be sent asynchronous
+   * @param connectionTimeout timeout for the HTTP connection
    * @param validStatusCodes a list of HTTP status codes which are considered as successful
    */
-  public HttpRecordSender(final URI uri, final boolean async,
+  public HttpRecordSender(
+      final URI uri,
+      final boolean async,
+      final Duration connectionTimeout,
       final List<Integer> validStatusCodes) {
     this.uri = uri;
     this.async = async;
+    this.connectionTimeout = connectionTimeout;
     this.validStatusCodes = validStatusCodes;
   }
 
@@ -64,6 +85,8 @@ public class HttpRecordSender<T extends SpecificRecord> implements RecordSender<
     final HttpRequest request = HttpRequest.newBuilder()
         .uri(this.uri)
         .POST(HttpRequest.BodyPublishers.ofString(json))
+        .header("Content-Type", "application/json")
+        .timeout(this.connectionTimeout)
         .build();
     final BodyHandler<Void> bodyHandler = BodyHandlers.discarding();
     // final BodyHandler<String> bodyHandler = BodyHandlers.ofString();
@@ -81,13 +104,19 @@ public class HttpRecordSender<T extends SpecificRecord> implements RecordSender<
                     response.statusCode());
               }
             });
-    if (this.async) {
+    if (this.isSync()) {
       try {
         result.get();
-      } catch (InterruptedException | ExecutionException e) {
+      } catch (final InterruptedException e) {
         LOGGER.error("Couldn't get result for request to {}.", this.uri, e);
+      } catch (final ExecutionException e) { // NOPMD
+        // Do nothing, Exception is already handled
       }
     }
   }
 
+  private boolean isSync() {
+    return !this.async;
+  }
+
 }
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/KafkaRecordSender.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/KafkaRecordSender.java
new file mode 100644
index 0000000000000000000000000000000000000000..56b1946ad78d888fe6e5140fdc373bb2cd3a4ed4
--- /dev/null
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/KafkaRecordSender.java
@@ -0,0 +1,137 @@
+package rocks.theodolite.benchmarks.loadgenerator;
+
+import java.util.Properties;
+import java.util.function.Function;
+import org.apache.avro.specific.SpecificRecord;
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.ProducerConfig;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.apache.kafka.common.serialization.Serializer;
+import org.apache.kafka.common.serialization.StringSerializer;
+import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory;
+
+/**
+ * Sends records to Kafka.
+ *
+ * @param <T> Record type to send.
+ */
+public interface KafkaRecordSender<T> extends RecordSender<T> {
+
+  @Override
+  public void close();
+
+  /**
+   * Creates a builder object for a {@link KafkaRecordSender} based on a Kafka {@link Serializer}.
+   *
+   * @param bootstrapServers The server to for accessing Kafka.
+   * @param topic The topic where to write.
+   * @param serializer The {@link Serializer} for mapping a value to keys.
+   */
+  public static <T> Builder<T> builderWithSerializer(
+      final String bootstrapServers,
+      final String topic,
+      final Serializer<T> serializer) {
+    return new Builder<>(bootstrapServers, topic, serializer);
+  }
+
+  /**
+   * Creates a Builder object for a {@link KafkaRecordSender} based on a Confluent Schema Registry
+   * URL.
+   *
+   * @param bootstrapServers The Server to for accessing Kafka.
+   * @param topic The topic where to write.
+   * @param schemaRegistryUrl URL to the schema registry for avro.
+   */
+  public static <T extends SpecificRecord> Builder<T> builderWithSchemaRegistry(
+      final String bootstrapServers,
+      final String topic,
+      final String schemaRegistryUrl) {
+    final SchemaRegistryAvroSerdeFactory avroSerdeFactory =
+        new SchemaRegistryAvroSerdeFactory(schemaRegistryUrl);
+    return new Builder<>(bootstrapServers, topic, avroSerdeFactory.<T>forValues().serializer());
+  }
+
+  /**
+   * Builder class to build a new {@link KafkaRecordSenderImpl}.
+   *
+   * @param <T> Type of the records that should later be send.
+   */
+  public static class Builder<T> {
+
+    private final String bootstrapServers;
+    private final String topic;
+    private final Serializer<T> serializer;
+    private Function<T, String> keyAccessor = x -> ""; // NOPMD
+    private Function<T, Long> timestampAccessor = x -> null; // NOPMD
+    private Properties defaultProperties = new Properties(); // NOPMD
+
+    private Builder(final String bootstrapServers, final String topic,
+        final Serializer<T> serializer) {
+      this.bootstrapServers = bootstrapServers;
+      this.topic = topic;
+      this.serializer = serializer;
+    }
+
+    public Builder<T> keyAccessor(final Function<T, String> keyAccessor) {
+      this.keyAccessor = keyAccessor;
+      return this;
+    }
+
+    public Builder<T> timestampAccessor(final Function<T, Long> timestampAccessor) {
+      this.timestampAccessor = timestampAccessor;
+      return this;
+    }
+
+    public Builder<T> defaultProperties(final Properties defaultProperties) {
+      this.defaultProperties = defaultProperties;
+      return this;
+    }
+
+    /**
+     * Create a {@link KafkaRecordSender} from this builder.
+     */
+    public KafkaRecordSender<T> build() {
+      final Properties properties = new Properties();
+      properties.putAll(this.defaultProperties);
+      properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, this.bootstrapServers);
+      // properties.put("acks", this.acknowledges);
+      // properties.put("batch.size", this.batchSize);
+      // properties.put("linger.ms", this.lingerMs);
+      // properties.put("buffer.memory", this.bufferMemory);
+
+      return new KafkaRecordSenderImpl<>(
+          new KafkaProducer<>(
+              properties,
+              new StringSerializer(),
+              this.serializer),
+          new DefaultRecordFactory<>(),
+          this.topic,
+          this.keyAccessor,
+          this.timestampAccessor);
+    }
+
+    private static class DefaultRecordFactory<T> implements KafkaRecordFactory<T, String, T> {
+
+      @Override
+      public ProducerRecord<String, T> create(final String topic, final String key, final T value,
+          final long timestamp) {
+        return new ProducerRecord<>(topic, null, timestamp, key, value);
+      }
+
+    }
+  }
+
+  /**
+   * Create Kafka {@link ProducerRecord}s from a topic, a key, a value and a timestamp.
+   *
+   * @param <T> type the records should be created from.
+   * @param <K> key type of the {@link ProducerRecord}s.
+   * @param <V> value type of the {@link ProducerRecord}s.
+   */
+  public static interface KafkaRecordFactory<T, K, V> {
+
+    ProducerRecord<K, V> create(String topic, String key, T value, long timestamp);
+
+  }
+
+}
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/KafkaRecordSenderImpl.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/KafkaRecordSenderImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..02a4d206b0a2414d5f12f5348f6c1bfc56852281
--- /dev/null
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/KafkaRecordSenderImpl.java
@@ -0,0 +1,70 @@
+package rocks.theodolite.benchmarks.loadgenerator;
+
+import java.util.function.Function;
+import org.apache.kafka.clients.producer.Producer;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.apache.kafka.common.errors.SerializationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Sends records to Kafka.
+ *
+ * @param <T> Record type to send.
+ * @param <K> Internal key type for Kafka records.
+ * @param <V> Internal value type for Kafka records.
+ */
+/* default */ class KafkaRecordSenderImpl<T, K, V> implements KafkaRecordSender<T> {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(KafkaRecordSenderImpl.class);
+
+  private final String topic;
+
+  private final Function<T, String> keyAccessor;
+
+  private final Function<T, Long> timestampAccessor;
+
+  private final Producer<K, V> producer;
+
+  private final KafkaRecordFactory<T, K, V> recordFactory;
+
+  /**
+   * Create a new {@link KafkaRecordSenderImpl}.
+   */
+  protected KafkaRecordSenderImpl(
+      final Producer<K, V> producer,
+      final KafkaRecordFactory<T, K, V> recordFactory,
+      final String topic,
+      final Function<T, String> keyAccessor,
+      final Function<T, Long> timestampAccessor) {
+    this.topic = topic;
+    this.producer = producer;
+    this.recordFactory = recordFactory;
+    this.keyAccessor = keyAccessor;
+    this.timestampAccessor = timestampAccessor;
+  }
+
+  @Override
+  public void close() {
+    this.producer.close();
+  }
+
+  @Override
+  public void send(final T message) {
+    final ProducerRecord<K, V> record = this.recordFactory.create(
+        this.topic,
+        this.keyAccessor.apply(message),
+        message,
+        this.timestampAccessor.apply(message));
+
+    LOGGER.debug("Send record to Kafka topic {}: {}", this.topic, record);
+    try {
+      this.producer.send(record);
+    } catch (final SerializationException e) {
+      LOGGER.warn(
+          "Record could not be serialized and thus not sent to Kafka due to exception. Skipping this record.", // NOCS
+          e);
+    }
+  }
+
+}
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/KeySpace.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/KeySpace.java
similarity index 78%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/KeySpace.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/KeySpace.java
index 51255d774427a9e00de0d4c921b884022585edab..82dac7b42dc6e16406f32d30f0dc7a372d7af43d 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/KeySpace.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/KeySpace.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 import java.io.Serializable;
 import java.util.Collection;
@@ -10,7 +10,7 @@ import java.util.stream.IntStream;
  */
 public class KeySpace implements Serializable {
 
-  private static final long serialVersionUID = 7343135392720315515L; // NOPMD
+  private static final long serialVersionUID = 7343135392720315516L; // NOPMD
 
   private final String prefix;
   private final int min;
@@ -18,11 +18,11 @@ public class KeySpace implements Serializable {
 
   /**
    * Create a new key space. All keys will have the prefix {@code prefix}. The remaining part of
-   * each key will be determined by a number of the interval ({@code min}, {@code max}).
+   * each key will be determined by a number of the interval [{@code min}, {@code max}).
    *
    * @param prefix the prefix to use for all keys
    * @param min the lower bound (inclusive) to start counting from
-   * @param max the upper bound (inclusive) to count to
+   * @param max the upper bound (exclusive) to count to
    */
   public KeySpace(final String prefix, final int min, final int max) {
     this.prefix = prefix;
@@ -31,7 +31,7 @@ public class KeySpace implements Serializable {
   }
 
   public KeySpace(final String prefix, final int numberOfKeys) {
-    this(prefix, 0, numberOfKeys - 1);
+    this(prefix, 0, numberOfKeys);
   }
 
   public String getPrefix() {
@@ -52,21 +52,21 @@ public class KeySpace implements Serializable {
    * Get the amount of keys in this {@link KeySpace}.
    */
   public int getCount() {
-    return this.getMax() - this.getMin() + 1;
+    return this.max - this.min;
   }
 
   /**
    * Get all keys in this {@link KeySpace}.
    */
   public Collection<String> getKeys() {
-    return IntStream.rangeClosed(this.min, this.max)
+    return IntStream.range(this.min, this.max)
         .mapToObj(id -> this.prefix + id)
         .collect(Collectors.toUnmodifiableList());
   }
 
   @Override
   public String toString() {
-    return this.prefix + '[' + this.min + '-' + this.max + ']';
+    return this.prefix + '[' + this.min + '-' + this.max + ')';
   }
 
 }
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/LoadGenerator.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/LoadGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..4be9b5695a54dedac6df78e6ceb8230752301e22
--- /dev/null
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/LoadGenerator.java
@@ -0,0 +1,112 @@
+package rocks.theodolite.benchmarks.loadgenerator;
+
+import java.time.Duration;
+import java.util.Objects;
+
+/**
+ * A Theodolite load generator.
+ */
+public final class LoadGenerator {
+
+  public static final String BOOTSTRAP_SERVER_DEFAULT = "localhost:5701";
+  public static final String SENSOR_PREFIX_DEFAULT = "s_";
+  public static final int NUMBER_OF_KEYS_DEFAULT = 10;
+  public static final int PERIOD_MS_DEFAULT = 1000;
+  public static final int VALUE_DEFAULT = 10;
+  public static final int THREADS_DEFAULT = 4;
+  public static final LoadGeneratorTarget TARGET_DEFAULT = LoadGeneratorTarget.KAFKA;
+  // Target: HTTP
+  public static final String HTTP_URI_DEFAULT = "http://localhost:8080";
+  public static final boolean HTTP_ASYNC_DEFAULT = false;
+  public static final long HTTP_TIMEOUT_MS_DEFAULT = 1_000;
+  // Target: Kafka
+  public static final String SCHEMA_REGISTRY_URL_DEFAULT = "http://localhost:8081";
+  public static final String KAFKA_TOPIC_DEFAULT = "input"; // NOCS
+  public static final String KAFKA_BOOTSTRAP_SERVERS_DEFAULT = "localhost:9092"; // NOPMD
+  // Target: Pub/Sub
+  public static final String PUBSUB_TOPIC_DEFAULT = "input"; // NOCS
+
+  private ClusterConfig clusterConfig;
+  private WorkloadDefinition loadDefinition;
+  private LoadGeneratorConfig generatorConfig;
+  private boolean isStarted;
+
+  private LoadGenerator() {}
+
+  // Add constructor for creating from environment variables
+
+  public LoadGenerator setClusterConfig(final ClusterConfig clusterConfig) { // NOPMD
+    this.clusterConfig = clusterConfig;
+    return this;
+  }
+
+  public LoadGenerator setLoadDefinition(final WorkloadDefinition loadDefinition) { // NOPMD
+    this.loadDefinition = loadDefinition;
+    return this;
+  }
+
+  public LoadGenerator setGeneratorConfig(final LoadGeneratorConfig generatorConfig) { // NOPMD
+    this.generatorConfig = generatorConfig;
+    return this;
+  }
+
+  public LoadGenerator withKeySpace(final KeySpace keySpace) {
+    this.loadDefinition = new WorkloadDefinition(keySpace, this.loadDefinition.getPeriod());
+    return this;
+  }
+
+  public LoadGenerator withBeforeAction(final BeforeAction beforeAction) {
+    this.generatorConfig.setBeforeAction(beforeAction);
+    return this;
+  }
+
+  public LoadGenerator withThreads(final int threads) {
+    this.generatorConfig.setThreads(threads);
+    return this;
+  }
+
+  /**
+   * Run the constructed load generator until cancellation.
+   */
+  public void run() {
+    Objects.requireNonNull(this.clusterConfig, "No cluster config set.");
+    Objects.requireNonNull(this.generatorConfig, "No generator config set.");
+    Objects.requireNonNull(this.loadDefinition, "No load definition set.");
+    if (this.isStarted) {
+      throw new IllegalStateException("Load generator can only be started once.");
+    }
+    this.isStarted = true;
+    final HazelcastRunner runner = new HazelcastRunner(
+        this.clusterConfig,
+        this.generatorConfig,
+        this.loadDefinition);
+    Runtime.getRuntime().addShutdownHook(new Thread(() -> runner.stop()));
+    runner.runBlocking();
+  }
+
+  /**
+   * Create a basic {@link LoadGenerator} from its default values.
+   */
+  public static LoadGenerator fromDefaults() {
+    return new LoadGenerator()
+        .setClusterConfig(ClusterConfig.fromBootstrapServer(BOOTSTRAP_SERVER_DEFAULT))
+        .setLoadDefinition(new WorkloadDefinition(
+            new KeySpace(SENSOR_PREFIX_DEFAULT, NUMBER_OF_KEYS_DEFAULT),
+            Duration.ofMillis(PERIOD_MS_DEFAULT)))
+        .setGeneratorConfig(new LoadGeneratorConfig(
+            GeneratorAction.from(
+                TitanRecordGenerator.forConstantValue(VALUE_DEFAULT),
+                TitanKafkaSenderFactory.forKafkaConfig(
+                    KAFKA_BOOTSTRAP_SERVERS_DEFAULT,
+                    KAFKA_TOPIC_DEFAULT,
+                    SCHEMA_REGISTRY_URL_DEFAULT))));
+  }
+
+  /**
+   * Create a basic {@link LoadGenerator} from environment variables.
+   */
+  public static LoadGenerator fromEnvironment() {
+    return new EnvVarLoadGeneratorFactory().create(new LoadGenerator());
+  }
+
+}
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorConfig.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/LoadGeneratorConfig.java
similarity index 50%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorConfig.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/LoadGeneratorConfig.java
index 4b5fea3e4670315ef47d94669b42a3cca4b5d0ae..e854138b38613ba614c871febcb80cf9c6b059ef 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorConfig.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/LoadGeneratorConfig.java
@@ -1,25 +1,20 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 /**
  * Configuration of a load generator.
  */
 public class LoadGeneratorConfig {
 
-  private final GeneratorAction messageGenerator;
+  private final GeneratorAction generatorAction;
   private BeforeAction beforeAction = BeforeAction.doNothing();
   private int threads = 1;
 
-  public <T> LoadGeneratorConfig(
-      final RecordGenerator<? extends T> generator,
-      final RecordSender<? super T> sender) {
-    this.messageGenerator = GeneratorAction.from(generator, sender);
+  public LoadGeneratorConfig(final GeneratorAction generatorAction) {
+    this.generatorAction = generatorAction;
   }
 
-  public <T> LoadGeneratorConfig(
-      final RecordGenerator<? extends T> generator,
-      final RecordSender<? super T> sender,
-      final int threads) {
-    this(generator, sender);
+  public LoadGeneratorConfig(final GeneratorAction generatorAction, final int threads) {
+    this(generatorAction);
     this.threads = threads;
   }
 
@@ -37,7 +32,7 @@ public class LoadGeneratorConfig {
 
   public LoadGeneratorExecution buildLoadGeneratorExecution(
       final WorkloadDefinition workloadDefinition) {
-    return new LoadGeneratorExecution(workloadDefinition, this.messageGenerator, this.threads);
+    return new LoadGeneratorExecution(workloadDefinition, this.generatorAction, this.threads);
   }
 
 }
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorExecution.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/LoadGeneratorExecution.java
similarity index 97%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorExecution.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/LoadGeneratorExecution.java
index e1a2a7e1bea964b5c69a6cd34374d7b0932bac03..809c93c2e4eb85657a4e773f70150fcef8817ed1 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorExecution.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/LoadGeneratorExecution.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 import java.util.Random;
 import java.util.concurrent.Executors;
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorTarget.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/LoadGeneratorTarget.java
similarity index 83%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorTarget.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/LoadGeneratorTarget.java
index 086e4de36301693c6873016122a47709b858a0d4..2fe7628d0d7611d0877847f5ff288d432feacc11 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorTarget.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/LoadGeneratorTarget.java
@@ -1,10 +1,10 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 import java.util.stream.Stream;
 
 enum LoadGeneratorTarget {
 
-  KAFKA("kafka"), HTTP("http");
+  HTTP("http"), KAFKA("kafka"), PUBSUB("pubsub");
 
   private final String value;
 
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/PubSubRecordSender.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/PubSubRecordSender.java
new file mode 100644
index 0000000000000000000000000000000000000000..ecba6961245651c7420d89c5da9bd1f993972188
--- /dev/null
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/PubSubRecordSender.java
@@ -0,0 +1,206 @@
+package rocks.theodolite.benchmarks.loadgenerator;
+
+import com.google.api.core.ApiFuture;
+import com.google.api.gax.core.CredentialsProvider;
+import com.google.api.gax.core.NoCredentialsProvider;
+import com.google.api.gax.grpc.GrpcTransportChannel;
+import com.google.api.gax.rpc.FixedTransportChannelProvider;
+import com.google.api.gax.rpc.TransportChannelProvider;
+import com.google.cloud.pubsub.v1.Publisher;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.util.Timestamps;
+import com.google.pubsub.v1.PubsubMessage;
+import com.google.pubsub.v1.TopicName;
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Sends monitoring records to Pub/Sub.
+ *
+ * @param <T> Record type to send
+ */
+public class PubSubRecordSender<T> implements RecordSender<T> {
+
+  private static final int SHUTDOWN_TIMEOUT_SEC = 5;
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(KafkaRecordSender.class);
+
+  private final Function<T, ByteBuffer> recordSerializer;
+
+  private final Function<T, Long> timestampAccessor;
+
+  private final Function<T, String> orderingKeyAccessor;
+
+  private final Publisher publisher;
+
+  private PubSubRecordSender(final Builder<T> builder) {
+    this.orderingKeyAccessor = builder.orderingKeyAccessor;
+    this.timestampAccessor = builder.timestampAccessor;
+    this.recordSerializer = builder.recordSerializer;
+
+    try {
+      this.publisher = builder.buildPublisher();
+    } catch (final IOException e) {
+      throw new IllegalStateException("Can not create Pub/Sub publisher.", e);
+    }
+  }
+
+  /**
+   * Terminate this {@link PubSubRecordSender} and shutdown the underlying {@link Publisher}.
+   */
+  @Override
+  public void close() {
+    this.publisher.shutdown();
+    try {
+      this.publisher.awaitTermination(SHUTDOWN_TIMEOUT_SEC, TimeUnit.SECONDS);
+    } catch (final InterruptedException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  @Override
+  public void send(final T record) {
+    final ByteBuffer byteBuffer = this.recordSerializer.apply(record);
+    final ByteString data = ByteString.copyFrom(byteBuffer);
+
+    final PubsubMessage.Builder messageBuilder = PubsubMessage.newBuilder().setData(data);
+    if (this.orderingKeyAccessor != null) {
+      messageBuilder.setOrderingKey(this.orderingKeyAccessor.apply(record));
+    }
+    if (this.timestampAccessor != null) {
+      messageBuilder.setPublishTime(Timestamps.fromMillis(this.timestampAccessor.apply(record)));
+    }
+    final PubsubMessage message = messageBuilder.build();
+    LOGGER.debug("Send message to PubSub topic {}: {}", this.publisher.getTopicName(), message);
+    final ApiFuture<String> publishResult = this.publisher.publish(message);
+    if (LOGGER.isDebugEnabled()) {
+      try {
+        LOGGER.debug("Publishing result is {}.", publishResult.get());
+      } catch (InterruptedException | ExecutionException e) {
+        LOGGER.warn("Can not get publishing result.", e);
+      }
+    }
+  }
+
+  /**
+   * Creates a {@link Builder} object for a {@link PubSubRecordSender}.
+   *
+   * @param project The project where to write.
+   * @param topic The topic where to write.
+   * @param recordSerializer A function serializing objects to {@link ByteBuffer}.
+   */
+  public static <T> Builder<T> builderForProject(
+      final String project,
+      final String topic,
+      final Function<T, ByteBuffer> recordSerializer) {
+    return new Builder<>(project, topic, recordSerializer);
+  }
+
+  /**
+   * Creates a {@link Builder} object for a {@link PubSubRecordSender}.
+   *
+   * @param emulatorHost Host of the emulator.
+   * @param topic The topic where to write.
+   * @param recordSerializer A function serializing objects to {@link ByteBuffer}.
+   */
+  public static <T> Builder<T> builderForEmulator(
+      final String emulatorHost,
+      final String topic,
+      final Function<T, ByteBuffer> recordSerializer) {
+    return new WithEmulatorBuilder<>(emulatorHost, topic, recordSerializer);
+  }
+
+  /**
+   * Builder class to build a new {@link PubSubRecordSender}.
+   *
+   * @param <T> Type of the records that should later be send.
+   */
+  public static class Builder<T> {
+
+    protected final TopicName topicName;
+    private final Function<T, ByteBuffer> recordSerializer; // NOPMD
+    private Function<T, Long> timestampAccessor = null; // NOPMD
+    private Function<T, String> orderingKeyAccessor = null; // NOPMD
+
+    /**
+     * Creates a Builder object for a {@link PubSubRecordSender}.
+     *
+     * @param topic The topic where to write.
+     * @param recordSerializer A function serializing objects to {@link ByteBuffer}.
+     */
+    private Builder(
+        final String project,
+        final String topic,
+        final Function<T, ByteBuffer> recordSerializer) {
+      this.topicName = TopicName.of(project, topic);
+      this.recordSerializer = recordSerializer;
+    }
+
+    public Builder<T> timestampAccessor(final Function<T, Long> timestampAccessor) {
+      this.timestampAccessor = timestampAccessor;
+      return this;
+    }
+
+    public Builder<T> orderingKeyAccessor(final Function<T, String> keyAccessor) {
+      this.orderingKeyAccessor = keyAccessor;
+      return this;
+    }
+
+    public PubSubRecordSender<T> build() {
+      return new PubSubRecordSender<>(this);
+    }
+
+    protected Publisher buildPublisher() throws IOException {
+      return Publisher.newBuilder(this.topicName).build();
+    }
+
+  }
+
+  private static class WithEmulatorBuilder<T> extends Builder<T> {
+
+    private static final String DUMMY_PROJECT = "dummy-project-id";
+
+    private final String emulatorHost;
+
+    /**
+     * Creates a Builder object for a {@link PubSubRecordSender}.
+     *
+     * @param emulatorHost host of the emulator.
+     * @param topic The topic where to write.
+     * @param recordSerializer A function serializing objects to {@link ByteBuffer}.
+     */
+    private WithEmulatorBuilder(
+        final String emulatorHost,
+        final String topic,
+        final Function<T, ByteBuffer> recordSerializer) {
+      super(DUMMY_PROJECT, topic, recordSerializer);
+      this.emulatorHost = emulatorHost;
+    }
+
+    @Override
+    protected Publisher buildPublisher() throws IOException {
+      final ManagedChannel channel = ManagedChannelBuilder
+          .forTarget(this.emulatorHost)
+          .usePlaintext()
+          .build();
+
+      final TransportChannelProvider channelProvider = FixedTransportChannelProvider
+          .create(GrpcTransportChannel.create(channel));
+      final CredentialsProvider credentialsProvider = NoCredentialsProvider.create();
+
+      return Publisher.newBuilder(super.topicName)
+          .setChannelProvider(channelProvider)
+          .setCredentialsProvider(credentialsProvider)
+          .build();
+    }
+
+  }
+
+}
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/RecordGenerator.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/RecordGenerator.java
similarity index 56%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/RecordGenerator.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/RecordGenerator.java
index ea6501f38ea57bf6cefb5c76b05f442454ca0d99..05e127eb019cf877cc5df73e09a6f053ef793fc3 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/RecordGenerator.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/RecordGenerator.java
@@ -1,4 +1,6 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
+
+import java.io.Closeable;
 
 /**
  * This interface describes a function that takes meta information from a string key and produces an
@@ -7,8 +9,13 @@ package theodolite.commons.workloadgeneration;
  * @param <T> the type of the objects that will be generated by the function.
  */
 @FunctionalInterface
-public interface RecordGenerator<T> {
+public interface RecordGenerator<T> extends Closeable {
 
   T generate(final String key);
 
+  @Override
+  default void close() {
+    // Nothing to do per default
+  }
+
 }
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/RecordSender.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/RecordSender.java
similarity index 58%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/RecordSender.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/RecordSender.java
index ee57f2f239a34dd6f8f329d47e4d698427e371b0..f1f1bef980f01da4a23b49440be71ba552c13905 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/RecordSender.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/RecordSender.java
@@ -1,4 +1,6 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
+
+import java.io.Closeable;
 
 /**
  * This interface describes a function that consumes a message {@code T}. This function is dedicated
@@ -7,8 +9,13 @@ package theodolite.commons.workloadgeneration;
  * @param <T> the type of records to send as messages.
  */
 @FunctionalInterface
-public interface RecordSender<T> {
+public interface RecordSender<T> extends Closeable {
 
   void send(final T message);
 
+  @Override
+  default void close() {
+    // Nothing to do per default
+  }
+
 }
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanKafkaSenderFactory.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanKafkaSenderFactory.java
similarity index 91%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanKafkaSenderFactory.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanKafkaSenderFactory.java
index 0cdf8d91ea01cc16df5dcd55d77b08c3f4986442..ee7d416513439a5d0ba7bad7bcdb09e1baf5e4c7 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanKafkaSenderFactory.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanKafkaSenderFactory.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 import java.util.Properties;
 import titan.ccp.model.records.ActivePowerRecord;
@@ -31,7 +31,7 @@ public final class TitanKafkaSenderFactory {
       final String schemaRegistryUrl,
       final Properties properties) {
     return KafkaRecordSender
-        .<ActivePowerRecord>builder(
+        .<ActivePowerRecord>builderWithSchemaRegistry(
             bootstrapServers,
             topic,
             schemaRegistryUrl)
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanPubSubSenderFactory.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanPubSubSenderFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..569d98fb9dcd235d12a0c415fdae495eeb6abdd4
--- /dev/null
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanPubSubSenderFactory.java
@@ -0,0 +1,50 @@
+package rocks.theodolite.benchmarks.loadgenerator;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * A factory for creating {@link PubSubRecordSender}s that sends Titan {@link ActivePowerRecord}s.
+ */
+public final class TitanPubSubSenderFactory {
+
+  private TitanPubSubSenderFactory() {}
+
+  /**
+   * Create a new {@link PubSubRecordSender} for {@link ActivePowerRecord}s for the given Pub/Sub
+   * configuration.
+   */
+  public static PubSubRecordSender<ActivePowerRecord> forPubSubConfig(
+      final String project,
+      final String topic) {
+    return PubSubRecordSender
+        .builderForProject(project, topic, TitanPubSubSenderFactory::serialize)
+        // .orderingKeyAccessor(r -> r.getIdentifier())
+        .timestampAccessor(r -> r.getTimestamp())
+        .build();
+  }
+
+  /**
+   * Create a new {@link PubSubRecordSender} for {@link ActivePowerRecord}s for the given PubSub
+   * emulator configuration.
+   */
+  public static PubSubRecordSender<ActivePowerRecord> forEmulatedPubSubConfig(
+      final String emulatorHost,
+      final String topic) {
+    return PubSubRecordSender
+        .builderForEmulator(emulatorHost, topic, TitanPubSubSenderFactory::serialize)
+        // .orderingKeyAccessor(r -> r.getIdentifier())
+        .timestampAccessor(r -> r.getTimestamp())
+        .build();
+  }
+
+  private static ByteBuffer serialize(final ActivePowerRecord record) {
+    try {
+      return record.toByteBuffer();
+    } catch (final IOException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+}
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanRecordGenerator.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanRecordGenerator.java
similarity index 95%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanRecordGenerator.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanRecordGenerator.java
index cebdacaee9a8e7d05787fdf3f846d49914574828..34b17db4220e60e1fd273b1acf0a0c1543a0742b 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanRecordGenerator.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanRecordGenerator.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 import java.time.Clock;
 import titan.ccp.model.records.ActivePowerRecord;
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/WorkloadDefinition.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/WorkloadDefinition.java
similarity index 84%
rename from theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/WorkloadDefinition.java
rename to theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/WorkloadDefinition.java
index 5795cad7a4d942476116f6453758aa2304b5eda0..1e7e6e5974323b545dd29b5db341405ffbd32eb3 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/WorkloadDefinition.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/WorkloadDefinition.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 import java.io.Serializable;
 import java.time.Duration;
@@ -42,16 +42,16 @@ public class WorkloadDefinition implements Serializable {
    * distributing its {@link KeySpace} (almost) equally among all {@link WorkloadDefinition}s.
    */
   public Set<WorkloadDefinition> divide(final int parts) {
-    final int effParts = Math.min(parts, this.keySpace.getCount());
-    final int minSize = this.keySpace.getCount() / effParts;
-    final int largerParts = this.keySpace.getCount() % effParts;
-    return IntStream.range(0, effParts)
+    // final int effParts = Math.min(parts, this.keySpace.getCount());
+    final int minSize = this.keySpace.getCount() / parts;
+    final int largerParts = this.keySpace.getCount() % parts;
+    return IntStream.range(0, parts)
         .mapToObj(part -> {
           final int thisSize = part < largerParts ? minSize + 1 : minSize;
           final int largePartsBefore = Math.min(largerParts, part);
           final int smallPartsBefore = part - largePartsBefore;
           final int start = largePartsBefore * (minSize + 1) + smallPartsBefore * minSize;
-          final int end = start + thisSize - 1;
+          final int end = start + thisSize;
           return new KeySpace(
               this.keySpace.getPrefix(),
               start,
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/KafkaRecordSender.java b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/KafkaRecordSender.java
deleted file mode 100644
index 44ff8a92afd5356b4bb2af203899a61f7af48b2d..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/KafkaRecordSender.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package theodolite.commons.workloadgeneration;
-
-import java.util.Properties;
-import java.util.function.Function;
-import org.apache.avro.specific.SpecificRecord;
-import org.apache.kafka.clients.producer.KafkaProducer;
-import org.apache.kafka.clients.producer.Producer;
-import org.apache.kafka.clients.producer.ProducerRecord;
-import org.apache.kafka.common.errors.SerializationException;
-import org.apache.kafka.common.serialization.StringSerializer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory;
-
-/**
- * Sends monitoring records to Kafka.
- *
- * @param <T> {@link SpecificRecord} to send
- */
-public class KafkaRecordSender<T extends SpecificRecord> implements RecordSender<T> {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(KafkaRecordSender.class);
-
-  private final String topic;
-
-  private final Function<T, String> keyAccessor;
-
-  private final Function<T, Long> timestampAccessor;
-
-  private final Producer<String, T> producer;
-
-  /**
-   * Create a new {@link KafkaRecordSender}.
-   */
-  private KafkaRecordSender(final Builder<T> builder) {
-    this.topic = builder.topic;
-    this.keyAccessor = builder.keyAccessor;
-    this.timestampAccessor = builder.timestampAccessor;
-
-    final Properties properties = new Properties();
-    properties.putAll(builder.defaultProperties);
-    properties.put("bootstrap.servers", builder.bootstrapServers);
-    // properties.put("acks", this.acknowledges);
-    // properties.put("batch.size", this.batchSize);
-    // properties.put("linger.ms", this.lingerMs);
-    // properties.put("buffer.memory", this.bufferMemory);
-
-    final SchemaRegistryAvroSerdeFactory avroSerdeFactory =
-        new SchemaRegistryAvroSerdeFactory(builder.schemaRegistryUrl);
-    this.producer = new KafkaProducer<>(
-        properties,
-        new StringSerializer(),
-        avroSerdeFactory.<T>forKeys().serializer());
-  }
-
-  /**
-   * Write the passed monitoring record to Kafka.
-   */
-  public void write(final T monitoringRecord) {
-    final ProducerRecord<String, T> record =
-        new ProducerRecord<>(this.topic, null, this.timestampAccessor.apply(monitoringRecord),
-            this.keyAccessor.apply(monitoringRecord), monitoringRecord);
-
-    LOGGER.debug("Send record to Kafka topic {}: {}", this.topic, record);
-    try {
-      this.producer.send(record);
-    } catch (final SerializationException e) {
-      LOGGER.warn(
-          "Record could not be serialized and thus not sent to Kafka due to exception. Skipping this record.", // NOCS
-          e);
-    }
-  }
-
-  public void terminate() {
-    this.producer.close();
-  }
-
-  @Override
-  public void send(final T message) {
-    this.write(message);
-  }
-
-  public static <T extends SpecificRecord> Builder<T> builder(
-      final String bootstrapServers,
-      final String topic,
-      final String schemaRegistryUrl) {
-    return new Builder<>(bootstrapServers, topic, schemaRegistryUrl);
-  }
-
-  /**
-   * Builder class to build a new {@link KafkaRecordSender}.
-   *
-   * @param <T> Type of the records that should later be send.
-   */
-  public static class Builder<T extends SpecificRecord> {
-
-    private final String bootstrapServers;
-    private final String topic;
-    private final String schemaRegistryUrl;
-    private Function<T, String> keyAccessor = x -> ""; // NOPMD
-    private Function<T, Long> timestampAccessor = x -> null; // NOPMD
-    private Properties defaultProperties = new Properties(); // NOPMD
-
-    /**
-     * Creates a Builder object for a {@link KafkaRecordSender}.
-     *
-     * @param bootstrapServers The Server to for accessing Kafka.
-     * @param topic The topic where to write.
-     * @param schemaRegistryUrl URL to the schema registry for avro.
-     */
-    private Builder(final String bootstrapServers, final String topic,
-        final String schemaRegistryUrl) {
-      this.bootstrapServers = bootstrapServers;
-      this.topic = topic;
-      this.schemaRegistryUrl = schemaRegistryUrl;
-    }
-
-    public Builder<T> keyAccessor(final Function<T, String> keyAccessor) {
-      this.keyAccessor = keyAccessor;
-      return this;
-    }
-
-    public Builder<T> timestampAccessor(final Function<T, Long> timestampAccessor) {
-      this.timestampAccessor = timestampAccessor;
-      return this;
-    }
-
-    public Builder<T> defaultProperties(final Properties defaultProperties) {
-      this.defaultProperties = defaultProperties;
-      return this;
-    }
-
-    public KafkaRecordSender<T> build() {
-      return new KafkaRecordSender<>(this);
-    }
-  }
-
-}
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGenerator.java b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGenerator.java
deleted file mode 100644
index 6453ef0bd3b6d5a3b5f7f2b77fa20da8f79cb35f..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGenerator.java
+++ /dev/null
@@ -1,206 +0,0 @@
-package theodolite.commons.workloadgeneration;
-
-import java.net.URI;
-import java.time.Duration;
-import java.util.Objects;
-import java.util.Properties;
-import org.apache.kafka.clients.producer.ProducerConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import titan.ccp.model.records.ActivePowerRecord;
-
-/**
- * A Theodolite load generator.
- */
-public final class LoadGenerator {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(LoadGenerator.class);
-
-  private static final String BOOTSTRAP_SERVER_DEFAULT = "localhost:5701";
-  private static final String SENSOR_PREFIX_DEFAULT = "s_";
-  private static final int NUMBER_OF_KEYS_DEFAULT = 10;
-  private static final int PERIOD_MS_DEFAULT = 1000;
-  private static final int VALUE_DEFAULT = 10;
-  private static final int THREADS_DEFAULT = 4;
-  private static final LoadGeneratorTarget TARGET_DEFAULT = LoadGeneratorTarget.KAFKA;
-  private static final String SCHEMA_REGISTRY_URL_DEFAULT = "http://localhost:8081";
-  private static final String KAFKA_TOPIC_DEFAULT = "input";
-  private static final String KAFKA_BOOTSTRAP_SERVERS_DEFAULT = "localhost:9092"; // NOPMD
-  private static final String HTTP_URI_DEFAULT = "http://localhost:8080";
-
-  private ClusterConfig clusterConfig;
-  private WorkloadDefinition loadDefinition;
-  private LoadGeneratorConfig generatorConfig;
-  private boolean isStarted;
-
-  private LoadGenerator() {}
-
-  // Add constructor for creating from environment variables
-
-  public LoadGenerator setClusterConfig(final ClusterConfig clusterConfig) { // NOPMD
-    this.clusterConfig = clusterConfig;
-    return this;
-  }
-
-  public LoadGenerator setLoadDefinition(final WorkloadDefinition loadDefinition) { // NOPMD
-    this.loadDefinition = loadDefinition;
-    return this;
-  }
-
-  public LoadGenerator setGeneratorConfig(final LoadGeneratorConfig generatorConfig) { // NOPMD
-    this.generatorConfig = generatorConfig;
-    return this;
-  }
-
-  public LoadGenerator withKeySpace(final KeySpace keySpace) {
-    this.loadDefinition = new WorkloadDefinition(keySpace, this.loadDefinition.getPeriod());
-    return this;
-  }
-
-  public LoadGenerator withBeforeAction(final BeforeAction beforeAction) {
-    this.generatorConfig.setBeforeAction(beforeAction);
-    return this;
-  }
-
-  public LoadGenerator withThreads(final int threads) {
-    this.generatorConfig.setThreads(threads);
-    return this;
-  }
-
-  /**
-   * Run the constructed load generator until cancellation.
-   */
-  public void run() {
-    Objects.requireNonNull(this.clusterConfig, "No cluster config set.");
-    Objects.requireNonNull(this.generatorConfig, "No generator config set.");
-    Objects.requireNonNull(this.loadDefinition, "No load definition set.");
-    if (this.isStarted) {
-      throw new IllegalStateException("Load generator can only be started once.");
-    }
-    this.isStarted = true;
-    final HazelcastRunner runner = new HazelcastRunner(
-        this.clusterConfig,
-        this.generatorConfig,
-        this.loadDefinition);
-    runner.runBlocking();
-  }
-
-  /**
-   * Create a basic {@link LoadGenerator} from its default values.
-   */
-  public static LoadGenerator fromDefaults() {
-    return new LoadGenerator()
-        .setClusterConfig(ClusterConfig.fromBootstrapServer(BOOTSTRAP_SERVER_DEFAULT))
-        .setLoadDefinition(new WorkloadDefinition(
-            new KeySpace(SENSOR_PREFIX_DEFAULT, NUMBER_OF_KEYS_DEFAULT),
-            Duration.ofMillis(PERIOD_MS_DEFAULT)))
-        .setGeneratorConfig(new LoadGeneratorConfig(
-            TitanRecordGenerator.forConstantValue(VALUE_DEFAULT),
-            TitanKafkaSenderFactory.forKafkaConfig(
-                KAFKA_BOOTSTRAP_SERVERS_DEFAULT,
-                KAFKA_TOPIC_DEFAULT,
-                SCHEMA_REGISTRY_URL_DEFAULT)));
-  }
-
-  /**
-   * Create a basic {@link LoadGenerator} from environment variables.
-   */
-  public static LoadGenerator fromEnvironment() {
-    final String bootstrapServer = System.getenv(ConfigurationKeys.BOOTSTRAP_SERVER);
-    final String kubernetesDnsName = System.getenv(ConfigurationKeys.KUBERNETES_DNS_NAME);
-
-    ClusterConfig clusterConfig;
-    if (bootstrapServer != null) { // NOPMD
-      clusterConfig = ClusterConfig.fromBootstrapServer(bootstrapServer);
-      LOGGER.info("Use bootstrap server '{}'.", bootstrapServer);
-    } else if (kubernetesDnsName != null) { // NOPMD
-      clusterConfig = ClusterConfig.fromKubernetesDnsName(kubernetesDnsName);
-      LOGGER.info("Use Kubernetes DNS name '{}'.", kubernetesDnsName);
-    } else {
-      clusterConfig = ClusterConfig.fromBootstrapServer(BOOTSTRAP_SERVER_DEFAULT);
-      LOGGER.info(
-          "Neither a bootstrap server nor a Kubernetes DNS name was provided. Use default bootstrap server '{}'.", // NOCS
-          BOOTSTRAP_SERVER_DEFAULT);
-    }
-
-    final String port = System.getenv(ConfigurationKeys.PORT);
-    if (port != null) {
-      clusterConfig.setPort(Integer.parseInt(port));
-    }
-
-    final String portAutoIncrement = System.getenv(ConfigurationKeys.PORT_AUTO_INCREMENT);
-    if (portAutoIncrement != null) {
-      clusterConfig.setPortAutoIncrement(Boolean.parseBoolean(portAutoIncrement));
-    }
-
-    final String clusterNamePrefix = System.getenv(ConfigurationKeys.CLUSTER_NAME_PREFIX);
-    if (clusterNamePrefix != null) {
-      clusterConfig.setClusterNamePrefix(portAutoIncrement);
-    }
-
-    final LoadGeneratorTarget target = LoadGeneratorTarget.from(
-        Objects.requireNonNullElse(System.getenv(ConfigurationKeys.TARGET),
-            TARGET_DEFAULT.getValue()));
-
-    final RecordSender<ActivePowerRecord> recordSender; // NOPMD
-    if (target == LoadGeneratorTarget.KAFKA) {
-      final String kafkaBootstrapServers = Objects.requireNonNullElse(
-          System.getenv(ConfigurationKeys.KAFKA_BOOTSTRAP_SERVERS),
-          KAFKA_BOOTSTRAP_SERVERS_DEFAULT);
-      final String kafkaInputTopic = Objects.requireNonNullElse(
-          System.getenv(ConfigurationKeys.KAFKA_INPUT_TOPIC),
-          KAFKA_TOPIC_DEFAULT);
-      final String schemaRegistryUrl = Objects.requireNonNullElse(
-          System.getenv(ConfigurationKeys.SCHEMA_REGISTRY_URL),
-          SCHEMA_REGISTRY_URL_DEFAULT);
-      final Properties kafkaProperties = new Properties();
-      kafkaProperties.compute(ProducerConfig.BATCH_SIZE_CONFIG,
-          (k, v) -> System.getenv(ConfigurationKeys.KAFKA_BATCH_SIZE));
-      kafkaProperties.compute(ProducerConfig.LINGER_MS_CONFIG,
-          (k, v) -> System.getenv(ConfigurationKeys.KAFKA_LINGER_MS));
-      kafkaProperties.compute(ProducerConfig.BUFFER_MEMORY_CONFIG,
-          (k, v) -> System.getenv(ConfigurationKeys.KAFKA_BUFFER_MEMORY));
-      recordSender = TitanKafkaSenderFactory.forKafkaConfig(
-          kafkaBootstrapServers,
-          kafkaInputTopic,
-          schemaRegistryUrl);
-      LOGGER.info(
-          "Use Kafka as target with bootstrap server '{}', schema registry url '{}' and topic '{}'.", // NOCS
-          kafkaBootstrapServers, schemaRegistryUrl, kafkaInputTopic);
-    } else if (target == LoadGeneratorTarget.HTTP) {
-      final URI url = URI.create(
-          Objects.requireNonNullElse(
-              System.getenv(ConfigurationKeys.HTTP_URL),
-              HTTP_URI_DEFAULT));
-      recordSender = new HttpRecordSender<>(url);
-      LOGGER.info("Use HTTP server as target with url '{}'.", url);
-    } else {
-      // Should never happen
-      throw new IllegalStateException("Target " + target + " is not handled yet.");
-    }
-
-    final int numSensors = Integer.parseInt(Objects.requireNonNullElse(
-        System.getenv(ConfigurationKeys.NUM_SENSORS),
-        Integer.toString(NUMBER_OF_KEYS_DEFAULT)));
-    final int periodMs = Integer.parseInt(Objects.requireNonNullElse(
-        System.getenv(ConfigurationKeys.PERIOD_MS),
-        Integer.toString(PERIOD_MS_DEFAULT)));
-    final double value = Double.parseDouble(Objects.requireNonNullElse(
-        System.getenv(ConfigurationKeys.VALUE),
-        Integer.toString(VALUE_DEFAULT)));
-    final int threads = Integer.parseInt(Objects.requireNonNullElse(
-        System.getenv(ConfigurationKeys.THREADS),
-        Integer.toString(THREADS_DEFAULT)));
-
-    return new LoadGenerator()
-        .setClusterConfig(clusterConfig)
-        .setLoadDefinition(new WorkloadDefinition(
-            new KeySpace(SENSOR_PREFIX_DEFAULT, numSensors),
-            Duration.ofMillis(periodMs)))
-        .setGeneratorConfig(new LoadGeneratorConfig(
-            TitanRecordGenerator.forConstantValue(value),
-            recordSender))
-        .withThreads(threads);
-  }
-
-}
diff --git a/theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/HttpRecordSenderTest.java b/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/HttpRecordSenderTest.java
similarity index 72%
rename from theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/HttpRecordSenderTest.java
rename to theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/HttpRecordSenderTest.java
index 6d908d34b7c6b87254782b6ae8b0b8dc2a6d036e..731dda6c74fd3cd6d74771f95896c2260ce6df29 100644
--- a/theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/HttpRecordSenderTest.java
+++ b/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/HttpRecordSenderTest.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
 import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
@@ -10,7 +10,6 @@ import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
 import static com.github.tomakehurst.wiremock.client.WireMock.verify;
 import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
 import com.github.tomakehurst.wiremock.junit.WireMockRule;
-import com.google.gson.Gson;
 import java.net.URI;
 import org.junit.Before;
 import org.junit.Rule;
@@ -21,8 +20,6 @@ public class HttpRecordSenderTest {
 
   private HttpRecordSender<ActivePowerRecord> httpRecordSender;
 
-  private Gson gson;
-
   @Rule
   public WireMockRule wireMockRule = new WireMockRule(options().dynamicPort());
 
@@ -30,7 +27,6 @@ public class HttpRecordSenderTest {
   public void setup() {
     this.httpRecordSender =
         new HttpRecordSender<>(URI.create("http://localhost:" + this.wireMockRule.port()));
-    this.gson = new Gson();
   }
 
   @Test
@@ -50,4 +46,22 @@ public class HttpRecordSenderTest {
         .withRequestBody(equalTo(expectedJson))); // toJson
   }
 
+  @Test
+  public void testTimeout() {
+    this.wireMockRule.stubFor(
+        post(urlPathEqualTo("/"))
+            .willReturn(
+                aResponse()
+                    .withFixedDelay(2_000)
+                    .withStatus(200)
+                    .withBody("received")));
+
+    final ActivePowerRecord record = new ActivePowerRecord("my-id", 12345L, 12.34);
+    this.httpRecordSender.send(record);
+
+    final String expectedJson = "{\"identifier\":\"my-id\",\"timestamp\":12345,\"valueInW\":12.34}";
+    verify(exactly(1), postRequestedFor(urlEqualTo("/"))
+        .withRequestBody(equalTo(expectedJson))); // toJson
+  }
+
 }
diff --git a/theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/KeySpaceTest.java b/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/KeySpaceTest.java
similarity index 75%
rename from theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/KeySpaceTest.java
rename to theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/KeySpaceTest.java
index 49004839a9c8fd280aba5006a1f08c2acb3c3136..cbd230433d2345cf00212cf6f68463d07c5ef765 100644
--- a/theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/KeySpaceTest.java
+++ b/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/KeySpaceTest.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 import org.junit.Assert;
 import org.junit.Test;
@@ -7,14 +7,14 @@ public class KeySpaceTest {
 
   @Test
   public void testCountFixedRangeFromZero() {
-    final KeySpace keySpace = new KeySpace("prefix", 0, 9);
+    final KeySpace keySpace = new KeySpace("prefix", 0, 10);
     final int count = keySpace.getCount();
     Assert.assertEquals(10, count);
   }
 
   @Test
   public void testCountFixedRangeNotFromZero() {
-    final KeySpace keySpace = new KeySpace("prefix", 4, 11);
+    final KeySpace keySpace = new KeySpace("prefix", 4, 12);
     final int count = keySpace.getCount();
     Assert.assertEquals(8, count);
   }
diff --git a/theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/LoadGeneratorTargetTest.java b/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/LoadGeneratorTargetTest.java
similarity index 92%
rename from theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/LoadGeneratorTargetTest.java
rename to theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/LoadGeneratorTargetTest.java
index 644ffad9a4d2732f72ac307294d1311eba3a9ce8..46f6d1081eae857d90489de49bbfd102c89b3821 100644
--- a/theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/LoadGeneratorTargetTest.java
+++ b/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/LoadGeneratorTargetTest.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 import org.junit.Assert;
 import org.junit.Test;
diff --git a/theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/TitanRecordGeneratorTest.java b/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/TitanRecordGeneratorTest.java
similarity index 96%
rename from theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/TitanRecordGeneratorTest.java
rename to theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/TitanRecordGeneratorTest.java
index 04ba38b9c8fcd41df46d3d3070a6308acfd72cb7..eb7c7f2a403dfb7138bdfd8e0855930001a4488b 100644
--- a/theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/TitanRecordGeneratorTest.java
+++ b/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/TitanRecordGeneratorTest.java
@@ -1,4 +1,4 @@
-package theodolite.commons.workloadgeneration;
+package rocks.theodolite.benchmarks.loadgenerator;
 
 import java.time.Clock;
 import java.time.Instant;
diff --git a/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/WorkloadDefinitionTest.java b/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/WorkloadDefinitionTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b670a73c6fe423e42e02c7d25d67311a5858c1af
--- /dev/null
+++ b/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/WorkloadDefinitionTest.java
@@ -0,0 +1,192 @@
+package rocks.theodolite.benchmarks.loadgenerator;
+
+import java.time.Duration;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class WorkloadDefinitionTest {
+
+  @Test
+  public void testDivideByOneAmount() {
+    final KeySpace keySpace = new KeySpace("prefix", 100);
+    final WorkloadDefinition workload = new WorkloadDefinition(keySpace, Duration.ofSeconds(1));
+    final Set<WorkloadDefinition> subworkloads = workload.divide(1);
+    Assert.assertEquals(1, subworkloads.size());
+  }
+
+  @Test
+  public void testDivideMultipleAmount() {
+    final KeySpace keySpace = new KeySpace("prefix", 100);
+    final WorkloadDefinition workload = new WorkloadDefinition(keySpace, Duration.ofSeconds(1));
+    final Set<WorkloadDefinition> subworkloads = workload.divide(2);
+    Assert.assertEquals(2, subworkloads.size());
+  }
+
+  @Test
+  public void testDivideNonMultipleAmount() {
+    final KeySpace keySpace = new KeySpace("prefix", 100);
+    final WorkloadDefinition workload = new WorkloadDefinition(keySpace, Duration.ofSeconds(1));
+    final Set<WorkloadDefinition> subworkloads = workload.divide(3);
+    Assert.assertEquals(3, subworkloads.size());
+  }
+
+  @Test
+  public void testDivide() {
+    final KeySpace keySpace = new KeySpace("prefix", 100);
+    final WorkloadDefinition workload = new WorkloadDefinition(keySpace, Duration.ofSeconds(1));
+    final Set<WorkloadDefinition> subworkloads = workload.divide(3);
+    Assert.assertEquals(3, subworkloads.size());
+    for (final WorkloadDefinition subworkload : subworkloads) {
+      Assert.assertEquals("prefix", subworkload.getKeySpace().getPrefix());
+      Assert.assertEquals(Duration.ofSeconds(1), subworkload.getPeriod());
+    }
+    final List<WorkloadDefinition> orderedSubworkloads = subworkloads.stream()
+        .sorted(Comparator.comparingInt(l -> l.getKeySpace().getMin()))
+        .collect(Collectors.toList());
+
+    final WorkloadDefinition subworkload1 = orderedSubworkloads.get(0);
+    final List<String> expectedKeySubworkload1 = IntStream
+        .rangeClosed(0, 33)
+        .mapToObj(id -> "prefix" + id)
+        .collect(Collectors.toList());
+    Assert.assertEquals(expectedKeySubworkload1, subworkload1.getKeySpace().getKeys());
+
+    final WorkloadDefinition subworkload2 = orderedSubworkloads.get(1);
+    final List<String> expectedKeySubworkload2 = IntStream
+        .rangeClosed(34, 66)
+        .mapToObj(id -> "prefix" + id)
+        .collect(Collectors.toList());
+    Assert.assertEquals(expectedKeySubworkload2, subworkload2.getKeySpace().getKeys());
+
+    final WorkloadDefinition subworkload3 = orderedSubworkloads.get(2);
+    final List<String> expectedKeySubworkload3 = IntStream
+        .rangeClosed(67, 99)
+        .mapToObj(id -> "prefix" + id)
+        .collect(Collectors.toList());
+    Assert.assertEquals(expectedKeySubworkload3, subworkload3.getKeySpace().getKeys());
+  }
+
+  @Test
+  public void testDivideMany() {
+    final KeySpace keySpace = new KeySpace("prefix", 10);
+    final WorkloadDefinition workload = new WorkloadDefinition(keySpace, Duration.ofSeconds(1));
+    final Set<WorkloadDefinition> subworkloads = workload.divide(7);
+    Assert.assertEquals(7, subworkloads.size());
+    for (final WorkloadDefinition subworkload : subworkloads) {
+      Assert.assertEquals("prefix", subworkload.getKeySpace().getPrefix());
+      Assert.assertEquals(Duration.ofSeconds(1), subworkload.getPeriod());
+    }
+    final List<WorkloadDefinition> orderedSubworkloads = subworkloads.stream()
+        .sorted(Comparator.comparingInt(l -> l.getKeySpace().getMin()))
+        .collect(Collectors.toList());
+
+    final WorkloadDefinition subworkload1 = orderedSubworkloads.get(0);
+    final List<String> expectedKeySubworkload1 = IntStream
+        .rangeClosed(0, 1)
+        .mapToObj(id -> "prefix" + id)
+        .collect(Collectors.toList());
+    Assert.assertEquals(expectedKeySubworkload1, subworkload1.getKeySpace().getKeys());
+
+    final WorkloadDefinition subworkload2 = orderedSubworkloads.get(1);
+    final List<String> expectedKeySubworkload2 = IntStream
+        .rangeClosed(2, 3)
+        .mapToObj(id -> "prefix" + id)
+        .collect(Collectors.toList());
+    Assert.assertEquals(expectedKeySubworkload2, subworkload2.getKeySpace().getKeys());
+
+    final WorkloadDefinition subworkload3 = orderedSubworkloads.get(2);
+    final List<String> expectedKeySubworkload3 = IntStream
+        .rangeClosed(4, 5)
+        .mapToObj(id -> "prefix" + id)
+        .collect(Collectors.toList());
+    Assert.assertEquals(expectedKeySubworkload3, subworkload3.getKeySpace().getKeys());
+
+    final WorkloadDefinition subworkload4 = orderedSubworkloads.get(3);
+    final List<String> expectedKeySubworkload4 = IntStream
+        .rangeClosed(6, 6)
+        .mapToObj(id -> "prefix" + id)
+        .collect(Collectors.toList());
+    Assert.assertEquals(expectedKeySubworkload4, subworkload4.getKeySpace().getKeys());
+
+    final WorkloadDefinition subworkload5 = orderedSubworkloads.get(4);
+    final List<String> expectedKeySubworkload5 = IntStream
+        .rangeClosed(7, 7)
+        .mapToObj(id -> "prefix" + id)
+        .collect(Collectors.toList());
+    Assert.assertEquals(expectedKeySubworkload5, subworkload5.getKeySpace().getKeys());
+
+    final WorkloadDefinition subworkload6 = orderedSubworkloads.get(5);
+    final List<String> expectedKeySubworkload6 = IntStream
+        .rangeClosed(8, 8)
+        .mapToObj(id -> "prefix" + id)
+        .collect(Collectors.toList());
+    Assert.assertEquals(expectedKeySubworkload6, subworkload6.getKeySpace().getKeys());
+
+    final WorkloadDefinition subworkload7 = orderedSubworkloads.get(6);
+    final List<String> expectedKeySubworkload7 = IntStream
+        .rangeClosed(9, 9)
+        .mapToObj(id -> "prefix" + id)
+        .collect(Collectors.toList());
+    Assert.assertEquals(expectedKeySubworkload7, subworkload7.getKeySpace().getKeys());
+  }
+
+  @Test
+  public void testDivideWithOneEmpty() {
+    final KeySpace keySpace = new KeySpace("prefix", 2);
+    final WorkloadDefinition workload = new WorkloadDefinition(keySpace, Duration.ofSeconds(1));
+    final Set<WorkloadDefinition> subworkloads = workload.divide(3);
+    Assert.assertEquals(3, subworkloads.size());
+    for (final WorkloadDefinition subworkload : subworkloads) {
+      Assert.assertEquals("prefix", subworkload.getKeySpace().getPrefix());
+      Assert.assertEquals(Duration.ofSeconds(1), subworkload.getPeriod());
+    }
+    final List<WorkloadDefinition> orderedSubworkloads = subworkloads.stream()
+        .sorted(Comparator.comparingInt(l -> l.getKeySpace().getMin()))
+        .collect(Collectors.toList());
+
+    final WorkloadDefinition subworkload1 = orderedSubworkloads.get(0);
+    final List<String> expectedKeySubworkload1 = List.of("prefix0");
+    Assert.assertEquals(expectedKeySubworkload1, subworkload1.getKeySpace().getKeys());
+
+    final WorkloadDefinition subworkload2 = orderedSubworkloads.get(1);
+    final List<String> expectedKeySubworkload2 = List.of("prefix1");
+    Assert.assertEquals(expectedKeySubworkload2, subworkload2.getKeySpace().getKeys());
+
+    final WorkloadDefinition subworkload3 = orderedSubworkloads.get(2);
+    final List<String> expectedKeySubworkload3 = List.of();
+    Assert.assertEquals(expectedKeySubworkload3, subworkload3.getKeySpace().getKeys());
+  }
+
+  @Test
+  public void testDivideWithTwoEmpty() {
+    final KeySpace keySpace = new KeySpace("prefix", 1);
+    final WorkloadDefinition workload = new WorkloadDefinition(keySpace, Duration.ofSeconds(1));
+    final Set<WorkloadDefinition> subworkloads = workload.divide(3);
+    Assert.assertEquals(3, subworkloads.size());
+    for (final WorkloadDefinition subworkload : subworkloads) {
+      Assert.assertEquals("prefix", subworkload.getKeySpace().getPrefix());
+      Assert.assertEquals(Duration.ofSeconds(1), subworkload.getPeriod());
+    }
+    final List<WorkloadDefinition> orderedSubworkloads = subworkloads.stream()
+        .sorted(Comparator.comparingInt(l -> l.getKeySpace().getMin()))
+        .collect(Collectors.toList());
+
+    final WorkloadDefinition subworkload1 = orderedSubworkloads.get(0);
+    final List<String> expectedKeySubworkload1 = List.of("prefix0");
+    Assert.assertEquals(expectedKeySubworkload1, subworkload1.getKeySpace().getKeys());
+
+    final WorkloadDefinition subworkload2 = orderedSubworkloads.get(1);
+    final List<String> expectedKeySubworkload2 = List.of();
+    Assert.assertEquals(expectedKeySubworkload2, subworkload2.getKeySpace().getKeys());
+
+    final WorkloadDefinition subworkload3 = orderedSubworkloads.get(2);
+    final List<String> expectedKeySubworkload3 = List.of();
+    Assert.assertEquals(expectedKeySubworkload3, subworkload3.getKeySpace().getKeys());
+  }
+
+}
diff --git a/theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/WorkloadDefinitionTest.java b/theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/WorkloadDefinitionTest.java
deleted file mode 100644
index 9a5dbf2d20e9e33b5902e5f352dc8a4023478cdf..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/load-generator-commons/src/test/java/theodolite/commons/workloadgeneration/WorkloadDefinitionTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package theodolite.commons.workloadgeneration;
-
-import java.time.Duration;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class WorkloadDefinitionTest {
-
-  @Test
-  public void testDivideByOneAmount() {
-    final KeySpace keySpace = new KeySpace("prefix", 100);
-    final WorkloadDefinition workload = new WorkloadDefinition(keySpace, Duration.ofSeconds(1));
-    final Set<WorkloadDefinition> subworkloads = workload.divide(1);
-    Assert.assertEquals(1, subworkloads.size());
-  }
-
-  @Test
-  public void testDivideMultipleAmount() {
-    final KeySpace keySpace = new KeySpace("prefix", 100);
-    final WorkloadDefinition workload = new WorkloadDefinition(keySpace, Duration.ofSeconds(1));
-    final Set<WorkloadDefinition> subworkloads = workload.divide(2);
-    Assert.assertEquals(2, subworkloads.size());
-  }
-
-  @Test
-  public void testDivideNonMultipleAmount() {
-    final KeySpace keySpace = new KeySpace("prefix", 100);
-    final WorkloadDefinition workload = new WorkloadDefinition(keySpace, Duration.ofSeconds(1));
-    final Set<WorkloadDefinition> subworkloads = workload.divide(3);
-    Assert.assertEquals(3, subworkloads.size());
-  }
-
-  @Test
-  public void testDivide() {
-    final KeySpace keySpace = new KeySpace("prefix", 100);
-    final WorkloadDefinition workload = new WorkloadDefinition(keySpace, Duration.ofSeconds(1));
-    final Set<WorkloadDefinition> subworkloads = workload.divide(3);
-    Assert.assertEquals(3, subworkloads.size());
-    for (final WorkloadDefinition subworkload : subworkloads) {
-      Assert.assertEquals("prefix", subworkload.getKeySpace().getPrefix());
-      Assert.assertEquals(Duration.ofSeconds(1), subworkload.getPeriod());
-    }
-    final List<WorkloadDefinition> orderedSubworkloads = subworkloads.stream()
-        .sorted(Comparator.comparingInt(l -> l.getKeySpace().getMin()))
-        .collect(Collectors.toList());
-    final WorkloadDefinition subworkload1 = orderedSubworkloads.get(0);
-    Assert.assertEquals(0, subworkload1.getKeySpace().getMin());
-    Assert.assertEquals(33, subworkload1.getKeySpace().getMax());
-    final WorkloadDefinition subworkload2 = orderedSubworkloads.get(1);
-    Assert.assertEquals(34, subworkload2.getKeySpace().getMin());
-    Assert.assertEquals(66, subworkload2.getKeySpace().getMax());
-    final WorkloadDefinition subworkload3 = orderedSubworkloads.get(2);
-    Assert.assertEquals(67, subworkload3.getKeySpace().getMin());
-    Assert.assertEquals(99, subworkload3.getKeySpace().getMax());
-  }
-
-  @Test
-  public void testDivideMany() {
-    final KeySpace keySpace = new KeySpace("prefix", 10);
-    final WorkloadDefinition workload = new WorkloadDefinition(keySpace, Duration.ofSeconds(1));
-    final Set<WorkloadDefinition> subworkloads = workload.divide(7);
-    Assert.assertEquals(7, subworkloads.size());
-    for (final WorkloadDefinition subworkload : subworkloads) {
-      Assert.assertEquals("prefix", subworkload.getKeySpace().getPrefix());
-      Assert.assertEquals(Duration.ofSeconds(1), subworkload.getPeriod());
-    }
-    final List<WorkloadDefinition> orderedSubworkloads = subworkloads.stream()
-        .sorted(Comparator.comparingInt(l -> l.getKeySpace().getMin()))
-        .collect(Collectors.toList());
-    final WorkloadDefinition subworkload1 = orderedSubworkloads.get(0);
-    Assert.assertEquals(0, subworkload1.getKeySpace().getMin());
-    Assert.assertEquals(1, subworkload1.getKeySpace().getMax());
-    final WorkloadDefinition subworkload2 = orderedSubworkloads.get(1);
-    Assert.assertEquals(2, subworkload2.getKeySpace().getMin());
-    Assert.assertEquals(3, subworkload2.getKeySpace().getMax());
-    final WorkloadDefinition subworkload3 = orderedSubworkloads.get(2);
-    Assert.assertEquals(4, subworkload3.getKeySpace().getMin());
-    Assert.assertEquals(5, subworkload3.getKeySpace().getMax());
-    final WorkloadDefinition subworkload4 = orderedSubworkloads.get(3);
-    Assert.assertEquals(6, subworkload4.getKeySpace().getMin());
-    Assert.assertEquals(6, subworkload4.getKeySpace().getMax());
-    final WorkloadDefinition subworkload5 = orderedSubworkloads.get(4);
-    Assert.assertEquals(7, subworkload5.getKeySpace().getMin());
-    Assert.assertEquals(7, subworkload5.getKeySpace().getMax());
-    final WorkloadDefinition subworkload6 = orderedSubworkloads.get(5);
-    Assert.assertEquals(8, subworkload6.getKeySpace().getMin());
-    Assert.assertEquals(8, subworkload6.getKeySpace().getMax());
-    final WorkloadDefinition subworkload7 = orderedSubworkloads.get(6);
-    Assert.assertEquals(9, subworkload7.getKeySpace().getMin());
-    Assert.assertEquals(9, subworkload7.getKeySpace().getMax());
-  }
-
-}
diff --git a/theodolite-benchmarks/settings.gradle b/theodolite-benchmarks/settings.gradle
index ae4254e968a0bc09970752f95c6a40db86ae775c..0040989a8b3b02487c2d7328726b7caadb90f32f 100644
--- a/theodolite-benchmarks/settings.gradle
+++ b/theodolite-benchmarks/settings.gradle
@@ -3,34 +3,40 @@ rootProject.name = 'theodolite-benchmarks'
 include 'load-generator-commons'
 include 'kstreams-commons'
 include 'flink-commons'
+include 'hazelcastjet-commons'
 include 'beam-commons'
 
-include 'uc1-beam'
-include 'uc2-beam'
-include 'uc3-beam'
-include 'uc4-beam'
-
 include 'uc1-load-generator'
+include 'uc1-commons'
 include 'uc1-kstreams'
 include 'uc1-flink'
+include 'uc1-hazelcastjet'
+include 'uc1-beam'
 include 'uc1-beam-flink'
 include 'uc1-beam-samza'
 
 include 'uc2-load-generator'
 include 'uc2-kstreams'
 include 'uc2-flink'
+include 'uc2-hazelcastjet'
+include 'uc2-beam'
 include 'uc2-beam-flink'
 include 'uc2-beam-samza'
 
 include 'uc3-load-generator'
 include 'uc3-kstreams'
 include 'uc3-flink'
+include 'uc3-hazelcastjet'
+include 'uc3-beam'
 include 'uc3-beam-flink'
 include 'uc3-beam-samza'
 
 include 'uc4-load-generator'
 include 'uc4-kstreams'
 include 'uc4-flink'
+include 'uc4-hazelcastjet'
+include 'uc4-beam'
 include 'uc4-beam-flink'
 include 'uc4-beam-samza'
 
+include 'http-bridge'
diff --git a/theodolite-benchmarks/uc1-beam-flink/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc1-beam-flink/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam-flink/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc1-beam-flink/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc1-beam-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc1-beam-flink/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc1-beam-flink/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam-flink/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc1-beam-flink/build.gradle b/theodolite-benchmarks/uc1-beam-flink/build.gradle
index f4b6cff8efbcdbcb701f249220643669f0f89626..fff1a0817b9bfd6f0c631c97aef585465ad15f4d 100644
--- a/theodolite-benchmarks/uc1-beam-flink/build.gradle
+++ b/theodolite-benchmarks/uc1-beam-flink/build.gradle
@@ -3,7 +3,17 @@ plugins {
 }
 
 dependencies {
-      implementation project(':uc1-beam')
+  implementation project(':uc1-beam')
 }
 
-mainClassName = "application.Uc1BeamFlink"
+sourceSets {
+  main {
+    resources {
+      srcDirs += [
+        project(':uc1-beam').sourceSets.main.resources
+      ]
+    }
+  }
+}
+
+mainClassName = "rocks.theodolite.benchmarks.uc1.beam.flink.Uc1BeamFlink"
diff --git a/theodolite-benchmarks/uc1-beam-flink/src/main/java/application/Uc1BeamFlink.java b/theodolite-benchmarks/uc1-beam-flink/src/main/java/application/Uc1BeamFlink.java
deleted file mode 100644
index fe58369b3c0c19351bcc5cde170df68946af7cbd..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc1-beam-flink/src/main/java/application/Uc1BeamFlink.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package application;
-
-import org.apache.beam.runners.flink.FlinkRunner;
-import theodolite.commons.beam.AbstractBeamService;
-
-/**
- * Implementation of the use case Database Storage using Apache Beam with the Flink Runner. To
- * execute locally in standalone start Kafka, Zookeeper, the schema-registry and the workload
- * generator using the delayed_startup.sh script. Start a Flink cluster and pass its REST adress
- * using--flinkMaster as run parameter. To persist logs add
- * ${workspace_loc:/uc1-application-samza/eclipseConsoleLogs.log} as Output File under Standard
- * Input Output in Common in the Run Configuration Start via Eclipse Run.
- */
-public final class Uc1BeamFlink extends AbstractBeamService {
-
-  /**
-   * Private constructor setting specific options for this use case.
-   */
-  private Uc1BeamFlink(final String[] args) { //NOPMD
-    super(args);
-    this.options.setRunner(FlinkRunner.class);
-  }
-
-  /**
-   * Main method.
-   */
-  public static void main(final String[] args) {
-
-    // Create application via configurations
-    final Uc1BeamFlink uc1 = new Uc1BeamFlink(args);
-
-    // Create pipeline with configurations
-    final Uc1BeamPipeline pipeline = new Uc1BeamPipeline(uc1.options, uc1.getConfig());
-
-    // Submit job and start execution
-    pipeline.run().waitUntilFinish();
-  }
-
-}
-
diff --git a/theodolite-benchmarks/uc1-beam-flink/src/main/java/rocks/theodolite/benchmarks/uc1/beam/flink/Uc1BeamFlink.java b/theodolite-benchmarks/uc1-beam-flink/src/main/java/rocks/theodolite/benchmarks/uc1/beam/flink/Uc1BeamFlink.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f39500433a77612fe5ab010372a24ca46035135
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam-flink/src/main/java/rocks/theodolite/benchmarks/uc1/beam/flink/Uc1BeamFlink.java
@@ -0,0 +1,24 @@
+package rocks.theodolite.benchmarks.uc1.beam.flink;
+
+import org.apache.beam.runners.flink.FlinkRunner;
+import rocks.theodolite.benchmarks.commons.beam.BeamService;
+import rocks.theodolite.benchmarks.uc1.beam.PipelineFactory;
+
+/**
+ * Implementation of the use case Database Storage using Apache Beam with the Flink Runner. To
+ * execute locally in standalone start Kafka, Zookeeper, the schema-registry and the workload
+ * generator using the delayed_startup.sh script. Start a Flink cluster and pass its REST adress
+ * using--flinkMaster as run parameter. To persist logs add
+ * ${workspace_loc:/uc1-application-samza/eclipseConsoleLogs.log} as Output File under Standard
+ * Input Output in Common in the Run Configuration Start via Eclipse Run.
+ */
+public final class Uc1BeamFlink {
+
+  private Uc1BeamFlink() {}
+
+  public static void main(final String[] args) {
+    new BeamService(PipelineFactory.factory(), FlinkRunner.class, args).runStandalone();
+  }
+
+}
+
diff --git a/theodolite-benchmarks/uc1-beam-samza/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc1-beam-samza/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam-samza/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc1-beam-samza/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc1-beam-samza/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam-samza/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc1-beam-samza/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc1-beam-samza/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam-samza/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc1-beam-samza/Dockerfile b/theodolite-benchmarks/uc1-beam-samza/Dockerfile
index 9b729060532ea3a242ac3084ba0bebf88ca2e9b6..cf6ef6675464e3c9d37db492b39fd8a71ec60e63 100644
--- a/theodolite-benchmarks/uc1-beam-samza/Dockerfile
+++ b/theodolite-benchmarks/uc1-beam-samza/Dockerfile
@@ -5,5 +5,5 @@ ENV MAX_SOURCE_PARALLELISM=1024
 ADD build/distributions/uc1-beam-samza.tar /
 ADD samza-standalone.properties /
 
-CMD /uc1-beam-samza/bin/uc1-beam-samza --configFactory=org.apache.samza.config.factories.PropertiesConfigFactory --configFilePath=samza-standalone.properties --samzaExecutionEnvironment=STANDALONE --maxSourceParallelism=$MAX_SOURCE_PARALLELISM --enableMetrics=false --configOverride="{\"job.coordinator.zk.connect\":\"$SAMZA_JOB_COORDINATOR_ZK_CONNECT\"}"
+CMD /uc1-beam-samza/bin/uc1-beam-samza --configFilePath=samza-standalone.properties --samzaExecutionEnvironment=STANDALONE --maxSourceParallelism=$MAX_SOURCE_PARALLELISM --enableMetrics=false --configOverride="{\"job.coordinator.zk.connect\":\"$SAMZA_JOB_COORDINATOR_ZK_CONNECT\"}"
 
diff --git a/theodolite-benchmarks/uc1-beam-samza/build.gradle b/theodolite-benchmarks/uc1-beam-samza/build.gradle
index 54c070d967d17ccd41c85f90486655c9fd56b65b..fab142f6d7a0f8415bda1cc0e41f088b952a11fb 100644
--- a/theodolite-benchmarks/uc1-beam-samza/build.gradle
+++ b/theodolite-benchmarks/uc1-beam-samza/build.gradle
@@ -6,5 +6,14 @@ dependencies {
   implementation project(':uc1-beam')
 }
 
+sourceSets {
+  main {
+    resources {
+      srcDirs += [
+        project(':uc1-beam').sourceSets.main.resources
+      ]
+    }
+  }
+}
 
-mainClassName = "application.Uc1BeamSamza"
+mainClassName = "rocks.theodolite.benchmarks.uc1.beam.samza.Uc1BeamSamza"
diff --git a/theodolite-benchmarks/uc1-beam-samza/src/main/java/application/Uc1BeamSamza.java b/theodolite-benchmarks/uc1-beam-samza/src/main/java/application/Uc1BeamSamza.java
deleted file mode 100644
index aaef5c2d6968c4b89059537277a2582ecca70451..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc1-beam-samza/src/main/java/application/Uc1BeamSamza.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package application;
-
-import org.apache.beam.runners.samza.SamzaRunner;
-import theodolite.commons.beam.AbstractBeamService;
-
-/**
- * Implementation of the use case Database Storage using Apache Beam with the Samza Runner. To
- * execute locally in standalone start Kafka, Zookeeper, the schema-registry and the workload
- * generator. Add
- * --configFactory=org.apache.samza.config.factories.PropertiesConfigFactory
- * --configFilePath=samza-standalone.properties
- * --samzaExecutionEnvironment=STANDALONE --maxSourceParallelism=1024 as program arguments. To
- * persist logs add ${workspace_loc:/uc4-application-samza/eclipseConsoleLogs.log} as Output File
- * under Standard Input Output in Common in the Run Configuration Start via Eclipse Run.
- */
-public final class Uc1BeamSamza extends AbstractBeamService {
-
-  /**
-   * Private constructor setting specific options for this use case.
-   */
-  private Uc1BeamSamza(final String[] args) { //NOPMD
-    super(args);
-    this.options.setRunner(SamzaRunner.class);
-  }
-
-  /**
-   * Main method.
-   */
-  public static void main(final String[] args) {
-
-    // Create application via configurations
-    final Uc1BeamSamza uc1 = new Uc1BeamSamza(args);
-
-    // Create pipeline with configurations
-    final Uc1BeamPipeline pipeline = new Uc1BeamPipeline(uc1.options, uc1.getConfig());
-
-    // Submit job and start execution
-    pipeline.run().waitUntilFinish();
-  }
-}
-
-
-
diff --git a/theodolite-benchmarks/uc1-beam-samza/src/main/java/rocks/theodolite/benchmarks/uc1/beam/samza/Uc1BeamSamza.java b/theodolite-benchmarks/uc1-beam-samza/src/main/java/rocks/theodolite/benchmarks/uc1/beam/samza/Uc1BeamSamza.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c3f650b7ddbe5e3c08139cdec2e590f5d55f3b3
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam-samza/src/main/java/rocks/theodolite/benchmarks/uc1/beam/samza/Uc1BeamSamza.java
@@ -0,0 +1,26 @@
+package rocks.theodolite.benchmarks.uc1.beam.samza;
+
+import org.apache.beam.runners.samza.SamzaRunner;
+import rocks.theodolite.benchmarks.commons.beam.BeamService;
+import rocks.theodolite.benchmarks.uc1.beam.PipelineFactory;
+
+/**
+ * Implementation of the use case Database Storage using Apache Beam with the Samza Runner. To
+ * execute locally in standalone start Kafka, Zookeeper, the schema-registry and the workload
+ * generator. Add --configFactory=org.apache.samza.config.factories.PropertiesConfigFactory
+ * --configFilePath=samza-standalone.properties --samzaExecutionEnvironment=STANDALONE
+ * --maxSourceParallelism=1024 as program arguments. To persist logs add
+ * ${workspace_loc:/uc4-application-samza/eclipseConsoleLogs.log} as Output File under Standard
+ * Input Output in Common in the Run Configuration Start via Eclipse Run.
+ */
+public final class Uc1BeamSamza {
+
+  private Uc1BeamSamza() {}
+
+  /**
+   * Main method.
+   */
+  public static void main(final String[] args) {
+    new BeamService(PipelineFactory.factory(), SamzaRunner.class, args).runStandalone();
+  }
+}
diff --git a/theodolite-benchmarks/uc1-beam-samza/src/main/resources/META-INF/application.properties b/theodolite-benchmarks/uc1-beam-samza/src/main/resources/META-INF/application.properties
deleted file mode 100644
index 50db1510ab5d7f6b8c9b1a75f112719209c351ce..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc1-beam-samza/src/main/resources/META-INF/application.properties
+++ /dev/null
@@ -1,16 +0,0 @@
-application.name=theodolite-uc1-application
-application.version=0.0.1
-
-kafka.bootstrap.servers=localhost:9092
-kafka.input.topic=input
-kafka.output.topic=output
-
-schema.registry.url=http://localhost:8081
-
-num.threads=1
-commit.interval.ms=1000
-cache.max.bytes.buffering=-1
-
-specific.avro.reader=True
-enable.auto.commit.config=True
-auto.offset.reset.config=earliest
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc1-beam/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc1-beam/.settings/org.eclipse.jdt.ui.prefs
index da2db2cefa90c0d974068e22804132eb6c11d824..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc1-beam/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc1-beam/.settings/org.eclipse.jdt.ui.prefs
@@ -105,6 +105,7 @@ cleanup.strictly_equal_or_different=false
 cleanup.stringbuffer_to_stringbuilder=false
 cleanup.stringbuilder=false
 cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
 cleanup.substring=false
 cleanup.switch=false
 cleanup.system_property=false
@@ -144,6 +145,7 @@ org.eclipse.jdt.ui.ignorelowercasenames=true
 org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
 sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
@@ -165,14 +167,14 @@ sp_cleanup.boolean_literal=false
 sp_cleanup.boolean_value_rather_than_comparison=false
 sp_cleanup.break_loop=false
 sp_cleanup.collection_cloning=false
-sp_cleanup.comparing_on_criteria=false
+sp_cleanup.comparing_on_criteria=true
 sp_cleanup.comparison_statement=false
 sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
-sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.convert_to_enhanced_for_loop=true
 sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
 sp_cleanup.convert_to_switch_expressions=false
-sp_cleanup.correct_indentation=false
+sp_cleanup.correct_indentation=true
 sp_cleanup.do_while_rather_than_while=false
 sp_cleanup.double_negation=false
 sp_cleanup.else_if=false
@@ -190,7 +192,7 @@ sp_cleanup.invert_equals=false
 sp_cleanup.join=false
 sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
-sp_cleanup.make_parameters_final=false
+sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
@@ -227,15 +229,15 @@ sp_cleanup.redundant_comparator=false
 sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
-sp_cleanup.remove_trailing_whitespaces=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
 sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
-sp_cleanup.remove_unnecessary_nls_tags=false
-sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
 sp_cleanup.remove_unused_local_variables=false
 sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
@@ -251,7 +253,8 @@ sp_cleanup.static_inner_class=false
 sp_cleanup.strictly_equal_or_different=false
 sp_cleanup.stringbuffer_to_stringbuilder=false
 sp_cleanup.stringbuilder=false
-sp_cleanup.stringbuilder_for_local_vars=true
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
 sp_cleanup.substring=false
 sp_cleanup.switch=false
 sp_cleanup.system_property=false
@@ -261,7 +264,7 @@ sp_cleanup.system_property_file_separator=false
 sp_cleanup.system_property_line_separator=false
 sp_cleanup.system_property_path_separator=false
 sp_cleanup.ternary_operator=false
-sp_cleanup.try_with_resource=true
+sp_cleanup.try_with_resource=false
 sp_cleanup.unlooped_while=false
 sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
@@ -278,6 +281,6 @@ sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
 sp_cleanup.use_unboxing=false
 sp_cleanup.use_var=false
-sp_cleanup.useless_continue=false
-sp_cleanup.useless_return=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
 sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc1-beam/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc1-beam/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc1-beam/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc1-beam/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc1-beam/build.gradle b/theodolite-benchmarks/uc1-beam/build.gradle
index 502e94fa737fb2ae1bab861407b27575cd8766ca..659eb09e67487132bca2b3ecb82298690dbf33c6 100644
--- a/theodolite-benchmarks/uc1-beam/build.gradle
+++ b/theodolite-benchmarks/uc1-beam/build.gradle
@@ -2,4 +2,7 @@ plugins {
   id 'theodolite.beam'
 }
 
-
+dependencies {
+  implementation project(':uc1-commons')
+  implementation 'org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.35.0'
+}
diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/application/LogKeyValue.java b/theodolite-benchmarks/uc1-beam/src/main/java/application/LogKeyValue.java
deleted file mode 100644
index 79566fd937b9c100663d426610b6ff476035ef87..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc1-beam/src/main/java/application/LogKeyValue.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package application;
-
-import org.apache.beam.sdk.transforms.DoFn;
-import org.apache.beam.sdk.values.KV;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Logs all Key Value pairs.
- */
-@SuppressWarnings({"unused"})
-public class LogKeyValue extends DoFn<KV<String, String>, KV<String, String>> {
-  private static final long serialVersionUID = 4328743;
-  private static final Logger LOGGER = LoggerFactory.getLogger(LogKeyValue.class);
-
-  /**
-   * Logs all key value pairs it processes.
-   */
-  @ProcessElement
-  public void processElement(@Element final KV<String, String> kv,
-      final OutputReceiver<KV<String, String>> out) {
-    if (LOGGER.isInfoEnabled()) {
-      LOGGER.info("Key: {}, Value: {}", kv.getKey(), kv.getValue());
-    }
-    out.output(kv);
-  }
-}
diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/application/MapToGson.java b/theodolite-benchmarks/uc1-beam/src/main/java/application/MapToGson.java
deleted file mode 100644
index 6b0c6bc4ddfe78c22028da5b8cf7dde7ed57fced..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc1-beam/src/main/java/application/MapToGson.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package application;
-
-import com.google.gson.Gson;
-import org.apache.beam.sdk.transforms.SimpleFunction;
-import org.apache.beam.sdk.values.KV;
-import titan.ccp.model.records.ActivePowerRecord;
-
-/**
- * Converts a Map into a json String.
- */
-public class MapToGson extends SimpleFunction<KV<String, ActivePowerRecord>, KV<String, String>> {
-  private static final long serialVersionUID = 7168356203579050214L;
-  private transient Gson gsonObj = new Gson();
-
-  @Override
-  public KV<String, String> apply(
-      final KV<String, ActivePowerRecord> kv) {
-
-    if (this.gsonObj == null) {
-      this.gsonObj = new Gson();
-    }
-
-    final String gson = this.gsonObj.toJson(kv.getValue());
-    return KV.of(kv.getKey(), gson);
-  }
-}
diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/application/Uc1BeamPipeline.java b/theodolite-benchmarks/uc1-beam/src/main/java/application/Uc1BeamPipeline.java
deleted file mode 100644
index eaff08ac78cd18ddfd47eb2949ca13340ecc27b8..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc1-beam/src/main/java/application/Uc1BeamPipeline.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package application;
-
-import java.util.Map;
-import org.apache.beam.sdk.coders.AvroCoder;
-import org.apache.beam.sdk.coders.CoderRegistry;
-import org.apache.beam.sdk.options.PipelineOptions;
-import org.apache.beam.sdk.transforms.MapElements;
-import org.apache.beam.sdk.transforms.ParDo;
-import org.apache.commons.configuration2.Configuration;
-import theodolite.commons.beam.AbstractPipeline;
-import theodolite.commons.beam.kafka.KafkaActivePowerTimestampReader;
-import titan.ccp.model.records.ActivePowerRecord;
-
-
-/**
- * Implementation of the use case Database Storage using Apache Beam with the Flink Runner. To
- * execute locally in standalone start Kafka, Zookeeper, the schema-registry and the workload
- * generator using the delayed_startup.sh script. Start a Flink cluster and pass its REST adress
- * using--flinkMaster as run parameter. To persist logs add
- * ${workspace_loc:/uc1-application-samza/eclipseConsoleLogs.log} as Output File under Standard
- * Input Output in Common in the Run Configuration Start via Eclipse Run.
- */
-public final class Uc1BeamPipeline extends AbstractPipeline {
-
-  protected Uc1BeamPipeline(final PipelineOptions options, final Configuration config) {
-    super(options, config);
-
-    // Set Coders for Classes that will be distributed
-    final CoderRegistry cr = this.getCoderRegistry();
-    cr.registerCoderForClass(ActivePowerRecord.class, AvroCoder.of(ActivePowerRecord.SCHEMA$));
-
-    // build KafkaConsumerConfig
-    final Map<String, Object> consumerConfig = this.buildConsumerConfig();
-
-    // Create Pipeline transformations
-    final KafkaActivePowerTimestampReader kafka =
-        new KafkaActivePowerTimestampReader(this.bootstrapServer, this.inputTopic, consumerConfig);
-
-    final LogKeyValue logKeyValue = new LogKeyValue();
-    final MapToGson mapToGson = new MapToGson();
-
-    // Apply pipeline transformations
-    // Read from Kafka
-    this.apply(kafka)
-        // Map to Gson
-        .apply(MapElements
-            .via(mapToGson))
-        // Print to console
-        .apply(ParDo.of(logKeyValue));
-  }
-}
-
diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/ConverterAdapter.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/ConverterAdapter.java
new file mode 100644
index 0000000000000000000000000000000000000000..08834a47223e8b4209da79c4cdcbb6a60e027418
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/ConverterAdapter.java
@@ -0,0 +1,40 @@
+package rocks.theodolite.benchmarks.uc1.beam;
+
+import org.apache.beam.sdk.transforms.SimpleFunction;
+import org.apache.beam.sdk.values.TypeDescriptor;
+import rocks.theodolite.benchmarks.uc1.commons.RecordConverter;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * {@link SimpleFunction} which wraps a {@link RecordConverter} to be used with Beam.
+ * 
+ * @param <T> type the {@link RecordConverter} is associated with.
+ */
+public class ConverterAdapter<T> extends SimpleFunction<ActivePowerRecord, T> {
+
+  private static final long serialVersionUID = -5263671231838353747L; // NOPMD
+
+  private final RecordConverter<T> recordConverter;
+  private final TypeDescriptor<T> type;
+
+  /**
+   * Create a new {@link ConverterAdapter} with a given {@link RecordConverter} and the associated
+   * type.
+   */
+  public ConverterAdapter(final RecordConverter<T> recordConverter, final Class<T> type) {
+    super();
+    this.recordConverter = recordConverter;
+    this.type = TypeDescriptor.of(type);
+  }
+
+  @Override
+  public T apply(final ActivePowerRecord record) {
+    return this.recordConverter.convert(record);
+  }
+
+  @Override
+  public TypeDescriptor<T> getOutputTypeDescriptor() {
+    return this.type;
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/GenericSink.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/GenericSink.java
new file mode 100644
index 0000000000000000000000000000000000000000..04eae799837b2e5278842d248d135e479f84086b
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/GenericSink.java
@@ -0,0 +1,41 @@
+package rocks.theodolite.benchmarks.uc1.beam;
+
+import org.apache.beam.sdk.transforms.MapElements;
+import org.apache.beam.sdk.transforms.PTransform;
+import org.apache.beam.sdk.transforms.ParDo;
+import org.apache.beam.sdk.values.PCollection;
+import rocks.theodolite.benchmarks.uc1.commons.DatabaseAdapter;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * A {@link PTransform} for a generic {@link DatabaseAdapter}.
+ *
+ * @param <T> Type parameter of {@link DatabaseAdapter}.
+ */
+public class GenericSink<T> extends PTransform<PCollection<ActivePowerRecord>, PCollection<?>> {
+
+  private static final long serialVersionUID = 1L;
+
+  private final DatabaseAdapter<T> databaseAdapter;
+  private final Class<T> type;
+
+  /**
+   * Create a {@link GenericSink} for the provided {@link DatabaseAdapter}. Requires also the
+   * corresponding {@link Class} object for Beam.
+   */
+  public GenericSink(final DatabaseAdapter<T> databaseAdapter, final Class<T> type) {
+    super();
+    this.databaseAdapter = databaseAdapter;
+    this.type = type;
+  }
+
+  @Override
+  public PCollection<?> expand(final PCollection<ActivePowerRecord> activePowerRecords) {
+    return activePowerRecords
+        .apply(MapElements
+            .via(new ConverterAdapter<>(this.databaseAdapter.getRecordConverter(), this.type)))
+        .apply(ParDo.of(new WriterAdapter<>(this.databaseAdapter.getDatabaseWriter())));
+
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/PipelineFactory.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/PipelineFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..d95d9b3343835f8348af15c3d00c34ef807d4501
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/PipelineFactory.java
@@ -0,0 +1,63 @@
+package rocks.theodolite.benchmarks.uc1.beam;
+
+import java.util.function.Function;
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.coders.AvroCoder;
+import org.apache.beam.sdk.coders.CoderRegistry;
+import org.apache.beam.sdk.options.PipelineOptions;
+import org.apache.beam.sdk.transforms.Values;
+import org.apache.commons.configuration2.Configuration;
+import rocks.theodolite.benchmarks.commons.beam.AbstractPipelineFactory;
+import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaActivePowerTimestampReader;
+import rocks.theodolite.benchmarks.uc1.beam.firestore.FirestoreOptionsExpander;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * {@link AbstractPipelineFactory} for UC1.
+ */
+public class PipelineFactory extends AbstractPipelineFactory {
+
+  public static final String SINK_TYPE_KEY = "sink.type";
+
+  private final SinkType sinkType = SinkType.from(this.config.getString(SINK_TYPE_KEY));
+
+  public PipelineFactory(final Configuration configuration) {
+    super(configuration);
+  }
+
+  @Override
+  protected void expandOptions(final PipelineOptions options) {
+    // No options to set
+    // TODO Add for PubSub
+    // final String pubSubEmulatorHost = super.config.getString(null);
+    // if (pubSubEmulatorHost != null) {
+    // final PubsubOptions pubSubOptions = options.as(PubsubOptions.class);
+    // pubSubOptions.setPubsubRootUrl("http://" + pubSubEmulatorHost);
+    // }
+    if (this.sinkType == SinkType.FIRESTORE) {
+      FirestoreOptionsExpander.expandOptions(options);
+    }
+  }
+
+  @Override
+  protected void constructPipeline(final Pipeline pipeline) {
+    final KafkaActivePowerTimestampReader kafkaReader = super.buildKafkaReader();
+
+    pipeline.apply(kafkaReader)
+        .apply(Values.create())
+        .apply(this.sinkType.create(this.config));
+  }
+
+  @Override
+  protected void registerCoders(final CoderRegistry registry) {
+    registry.registerCoderForClass(
+        ActivePowerRecord.class,
+        // AvroCoder.of(ActivePowerRecord.SCHEMA$));
+        AvroCoder.of(ActivePowerRecord.class, false));
+  }
+
+  public static Function<Configuration, AbstractPipelineFactory> factory() {
+    return config -> new PipelineFactory(config);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/SinkFactory.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/SinkFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..d4854293b0c26804f0204e58c09a45f13dbf171f
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/SinkFactory.java
@@ -0,0 +1,16 @@
+package rocks.theodolite.benchmarks.uc1.beam;
+
+import org.apache.beam.sdk.transforms.PTransform;
+import org.apache.beam.sdk.values.PCollection;
+import org.apache.commons.configuration2.Configuration;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * Interface for a class that creates sinks (i.e., {@link PTransform}s that map and store
+ * {@link ActivePowerRecord}s, optionally, using a {@link Configuration}.
+ */
+public interface SinkFactory {
+
+  PTransform<PCollection<ActivePowerRecord>, PCollection<?>> create(Configuration configuration);
+
+}
diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/SinkType.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/SinkType.java
new file mode 100644
index 0000000000000000000000000000000000000000..da836815e09631e2ebc071badc02618171e0792a
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/SinkType.java
@@ -0,0 +1,52 @@
+package rocks.theodolite.benchmarks.uc1.beam;
+
+import java.util.stream.Stream;
+import org.apache.beam.sdk.transforms.PTransform;
+import org.apache.beam.sdk.values.PCollection;
+import org.apache.commons.configuration2.Configuration;
+import rocks.theodolite.benchmarks.uc1.beam.firestore.FirestoreSink;
+import rocks.theodolite.benchmarks.uc1.commons.logger.LogWriterFactory;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * Supported Sink types, i.e., {@link PTransform} for converting and storing
+ * {@link ActivePowerRecord}s.
+ */
+public enum SinkType implements SinkFactory {
+
+  LOGGER("logger") {
+    @Override
+    public PTransform<PCollection<ActivePowerRecord>, PCollection<?>> create(
+        final Configuration config) {
+      return new GenericSink<>(LogWriterFactory.forJson(), String.class);
+    }
+  },
+  FIRESTORE("firestore") {
+    @Override
+    public PTransform<PCollection<ActivePowerRecord>, PCollection<?>> create(
+        final Configuration config) {
+      return FirestoreSink.fromConfig(config);
+    }
+  };
+
+  private final String value;
+
+  SinkType(final String value) {
+    this.value = value;
+  }
+
+  public String getValue() {
+    return this.value;
+  }
+
+  /**
+   * Create a new {@link SinkType} from its string representation.
+   */
+  public static SinkType from(final String value) {
+    return Stream.of(SinkType.values())
+        .filter(t -> t.value.equals(value))
+        .findFirst()
+        .orElseThrow(() -> new IllegalArgumentException("Sink '" + value + "' does not exist."));
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/WriterAdapter.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/WriterAdapter.java
new file mode 100644
index 0000000000000000000000000000000000000000..c1dc2f7305d01b47de644e4f8d391955540f530c
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/WriterAdapter.java
@@ -0,0 +1,28 @@
+package rocks.theodolite.benchmarks.uc1.beam;
+
+import org.apache.beam.sdk.transforms.DoFn;
+import rocks.theodolite.benchmarks.uc1.commons.DatabaseAdapter;
+import rocks.theodolite.benchmarks.uc1.commons.DatabaseWriter;
+
+/**
+ * {@link DoFn} which wraps a {@link DatabaseAdapter} to be used with Beam.
+ *
+ * @param <T> type the {@link DatabaseWriter} is associated with.
+ */
+public class WriterAdapter<T> extends DoFn<T, Void> {
+
+  private static final long serialVersionUID = -5263671231838353742L; // NOPMD
+
+  private final DatabaseWriter<T> databaseWriter;
+
+  public WriterAdapter(final DatabaseWriter<T> databaseWriter) {
+    super();
+    this.databaseWriter = databaseWriter;
+  }
+
+  @ProcessElement
+  public void processElement(@Element final T record, final OutputReceiver<Void> out) {
+    this.databaseWriter.write(record);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/DocumentMapper.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/DocumentMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..1abf847250779150bb48b45c162afaeac1130044
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/DocumentMapper.java
@@ -0,0 +1,52 @@
+package rocks.theodolite.benchmarks.uc1.beam.firestore;
+
+import com.google.firestore.v1.Document;
+import com.google.firestore.v1.Value;
+import java.io.IOException;
+import org.apache.beam.sdk.transforms.SimpleFunction;
+import titan.ccp.model.records.ActivePowerRecord;
+
+final class DocumentMapper extends SimpleFunction<ActivePowerRecord, Document> {
+
+  private static final long serialVersionUID = -5263671231838353749L; // NOPMD
+
+  private transient FirestoreConfig firestoreConfig;
+
+  private final String collection;
+
+  public DocumentMapper(final String collection) {
+    super();
+    this.collection = collection;
+  }
+
+  @Override
+  public Document apply(final ActivePowerRecord record) {
+    return Document
+        .newBuilder()
+        .setName(this.createDocumentName(record.getIdentifier() + record.getTimestamp()))
+        .putFields("identifier",
+            Value.newBuilder().setStringValue(record.getIdentifier()).build())
+        .putFields("timestamp", Value.newBuilder().setIntegerValue(record.getTimestamp()).build())
+        .putFields("valueInW", Value.newBuilder().setDoubleValue(record.getValueInW()).build())
+        .build();
+  }
+
+  private String createDocumentName(final String documentId) {
+    this.initFirestoreConfig();
+    return "projects/" + this.firestoreConfig.getProjectId()
+        + "/databases/" + this.firestoreConfig.getDatabase()
+        + "/documents/" + this.collection
+        + "/" + documentId;
+  }
+
+  private void initFirestoreConfig() {
+    if (this.firestoreConfig == null) {
+      try {
+        this.firestoreConfig = FirestoreConfig.createFromDefaults();
+      } catch (final IOException e) {
+        throw new IllegalStateException("Cannot create Firestore configuration.", e);
+      }
+    }
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/FirestoreConfig.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/FirestoreConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..143387d0e15fc778721e026f1c7fdb3b01fc15ef
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/FirestoreConfig.java
@@ -0,0 +1,29 @@
+package rocks.theodolite.benchmarks.uc1.beam.firestore;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import com.google.cloud.firestore.FirestoreOptions;
+import java.io.IOException;
+
+final class FirestoreConfig {
+
+  private final FirestoreOptions firestoreOptions;
+
+  private FirestoreConfig(final FirestoreOptions firestoreOptions) {
+    this.firestoreOptions = firestoreOptions;
+  }
+
+  public String getProjectId() {
+    return this.firestoreOptions.getProjectId();
+  }
+
+  public String getDatabase() {
+    return this.firestoreOptions.getDatabaseId();
+  }
+
+  public static FirestoreConfig createFromDefaults() throws IOException {
+    return new FirestoreConfig(FirestoreOptions.getDefaultInstance().toBuilder()
+        .setCredentials(GoogleCredentials.getApplicationDefault())
+        .build());
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/FirestoreOptionsExpander.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/FirestoreOptionsExpander.java
new file mode 100644
index 0000000000000000000000000000000000000000..0447450b45b971f96e2f2cbb7ce91f78604d5a23
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/FirestoreOptionsExpander.java
@@ -0,0 +1,34 @@
+package rocks.theodolite.benchmarks.uc1.beam.firestore;
+
+import java.io.IOException;
+import org.apache.beam.sdk.extensions.gcp.options.GcpOptions;
+import org.apache.beam.sdk.options.PipelineOptions;
+
+/**
+ * Provides a method to expand {@link PipelineOptions} for Firestore.
+ */
+public final class FirestoreOptionsExpander {
+
+  private FirestoreOptionsExpander() {}
+
+  /**
+   * Expand {@link PipelineOptions} by special options required for Firestore derived from a default
+   * configuration.
+   *
+   * @param options {@link PipelineOptions} to be expanded.
+   */
+  public static void expandOptions(final PipelineOptions options) {
+    final GcpOptions firestoreOptions = options.as(GcpOptions.class);
+    final FirestoreConfig firestoreConfig = getFirestoreConfig();
+    firestoreOptions.setProject(firestoreConfig.getProjectId());
+  }
+
+  private static FirestoreConfig getFirestoreConfig() {
+    try {
+      return FirestoreConfig.createFromDefaults();
+    } catch (final IOException e) {
+      throw new IllegalStateException("Cannot create Firestore configuration.", e);
+    }
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/FirestoreSink.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/FirestoreSink.java
new file mode 100644
index 0000000000000000000000000000000000000000..dfe3f240b9727d0fa5027ea5f29cd67def3323ba
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/FirestoreSink.java
@@ -0,0 +1,41 @@
+package rocks.theodolite.benchmarks.uc1.beam.firestore;
+
+import com.google.cloud.firestore.DocumentSnapshot;
+import com.google.firestore.v1.Document;
+import org.apache.beam.sdk.io.gcp.firestore.FirestoreIO;
+import org.apache.beam.sdk.transforms.MapElements;
+import org.apache.beam.sdk.transforms.PTransform;
+import org.apache.beam.sdk.values.PCollection;
+import org.apache.commons.configuration2.Configuration;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * A {@link PTransform} mapping {@link ActivePowerRecord}s to {@link Document}s, followed by storing
+ * these {@link DocumentSnapshot} to Firestore.
+ */
+public class FirestoreSink extends PTransform<PCollection<ActivePowerRecord>, PCollection<?>> {
+
+  public static final String SINK_FIRESTORE_COLLECTION_KEY = "sink.firestore.collection";
+
+  private static final long serialVersionUID = 1L;
+
+  private final String collectionName;
+
+  public FirestoreSink(final String collectionName) {
+    super();
+    this.collectionName = collectionName;
+  }
+
+  @Override
+  public PCollection<?> expand(final PCollection<ActivePowerRecord> activePowerRecords) {
+    return activePowerRecords
+        .apply(MapElements.via(new DocumentMapper(this.collectionName)))
+        .apply(MapElements.via(new UpdateOperationMapper()))
+        .apply(FirestoreIO.v1().write().batchWrite().build());
+  }
+
+  public static FirestoreSink fromConfig(final Configuration config) {
+    final String collectionName = config.getString(SINK_FIRESTORE_COLLECTION_KEY);
+    return new FirestoreSink(collectionName);
+  }
+}
diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/UpdateOperationMapper.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/UpdateOperationMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc1170073477eabd7b340f59e97ef8cbe1cf3743
--- /dev/null
+++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/UpdateOperationMapper.java
@@ -0,0 +1,18 @@
+package rocks.theodolite.benchmarks.uc1.beam.firestore;
+
+import com.google.firestore.v1.Document;
+import com.google.firestore.v1.Write;
+import org.apache.beam.sdk.transforms.SimpleFunction;
+
+final class UpdateOperationMapper extends SimpleFunction<Document, Write> {
+
+  private static final long serialVersionUID = -5263671231838353748L; // NOPMD
+
+  @Override
+  public Write apply(final Document document) {
+    return Write.newBuilder()
+        .setUpdate(document)
+        .build();
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-beam-flink/src/main/resources/META-INF/application.properties b/theodolite-benchmarks/uc1-beam/src/main/resources/META-INF/application.properties
similarity index 66%
rename from theodolite-benchmarks/uc1-beam-flink/src/main/resources/META-INF/application.properties
rename to theodolite-benchmarks/uc1-beam/src/main/resources/META-INF/application.properties
index 50db1510ab5d7f6b8c9b1a75f112719209c351ce..e9de96c0df34b1254a8ec9886586e163999c7c6e 100644
--- a/theodolite-benchmarks/uc1-beam-flink/src/main/resources/META-INF/application.properties
+++ b/theodolite-benchmarks/uc1-beam/src/main/resources/META-INF/application.properties
@@ -1,6 +1,9 @@
 application.name=theodolite-uc1-application
 application.version=0.0.1
 
+sink.type=logger
+source.type=kafka
+
 kafka.bootstrap.servers=localhost:9092
 kafka.input.topic=input
 kafka.output.topic=output
@@ -11,6 +14,7 @@ num.threads=1
 commit.interval.ms=1000
 cache.max.bytes.buffering=-1
 
-specific.avro.reader=True
-enable.auto.commit.config=True
-auto.offset.reset.config=earliest
\ No newline at end of file
+specific.avro.reader=true
+enable.auto.commit=true
+max.poll.records=500
+auto.offset.reset=earliest
diff --git a/theodolite-benchmarks/uc1-commons/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc1-commons/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/uc1-commons/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc1-commons/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc1-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc1-commons/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc1-commons/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc1-commons/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc1-commons/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc1-commons/build.gradle b/theodolite-benchmarks/uc1-commons/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..0f7d31d1f557ecd214b3a57227851d0f70b61084
--- /dev/null
+++ b/theodolite-benchmarks/uc1-commons/build.gradle
@@ -0,0 +1,24 @@
+plugins {
+    id 'theodolite.java-commons'
+}
+
+repositories {
+  mavenCentral()
+  maven {
+    url "https://oss.sonatype.org/content/repositories/snapshots/"
+  }
+  maven {
+    url 'https://packages.confluent.io/maven/'
+  }
+}
+
+dependencies {
+  // Make this implementation once this is a local subproject.
+  // Currently, Flink needs its own version of these dependencies.
+  compileOnly('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true }
+  compileOnly('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true }
+
+  implementation 'com.google.code.gson:gson:2.8.9'
+
+  testImplementation 'junit:junit:4.12'
+}
diff --git a/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/DatabaseAdapter.java b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/DatabaseAdapter.java
new file mode 100644
index 0000000000000000000000000000000000000000..a1cb1ade0dc76b168cf9ee54f64d5ac88d6b3a98
--- /dev/null
+++ b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/DatabaseAdapter.java
@@ -0,0 +1,46 @@
+package rocks.theodolite.benchmarks.uc1.commons;
+
+import java.util.Objects;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * A database adapter consisting of a {@link RecordConverter} and a {@link DatabaseWriter}.
+ *
+ * @param <T> intermediate data type written to the database.
+ */
+public final class DatabaseAdapter<T> {
+
+  private final RecordConverter<T> recordConverter;
+
+  private final DatabaseWriter<T> databaseWriter;
+
+  private DatabaseAdapter(final RecordConverter<T> recordConverter,
+      final DatabaseWriter<T> databaseWriter) {
+    this.recordConverter = recordConverter;
+    this.databaseWriter = databaseWriter;
+  }
+
+  public RecordConverter<T> getRecordConverter() {
+    return this.recordConverter;
+  }
+
+  public DatabaseWriter<T> getDatabaseWriter() {
+    return this.databaseWriter;
+  }
+
+  /**
+   * Create a new {@link DatabaseAdapter}.
+   *
+   * @param <T> intermediate data type written to the database.
+   * @param recordConverter RecordConverter for converting {@link ActivePowerRecord}s to {@code T}
+   * @param databaseWriter DatabaseWriter for writing converted records to the database.
+   * @return the {@link DatabaseAdapter}.
+   */
+  public static <T> DatabaseAdapter<T> from(final RecordConverter<T> recordConverter,
+      final DatabaseWriter<T> databaseWriter) {
+    Objects.requireNonNull(recordConverter);
+    Objects.requireNonNull(databaseWriter);
+    return new DatabaseAdapter<>(recordConverter, databaseWriter);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/DatabaseWriter.java b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/DatabaseWriter.java
new file mode 100644
index 0000000000000000000000000000000000000000..1beb269e4b75252ac72f7c30c4a26f7a11de4fb6
--- /dev/null
+++ b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/DatabaseWriter.java
@@ -0,0 +1,13 @@
+package rocks.theodolite.benchmarks.uc1.commons;
+
+/**
+ * Writes an object to a database.
+ *
+ * @param <T> Type expected by the database.
+ */
+@FunctionalInterface
+public interface DatabaseWriter<T> {
+
+  void write(T record);
+
+}
diff --git a/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/RecordConverter.java b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/RecordConverter.java
new file mode 100644
index 0000000000000000000000000000000000000000..105f19e0e920e3516f7277cd7804dae210a7d0b1
--- /dev/null
+++ b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/RecordConverter.java
@@ -0,0 +1,15 @@
+package rocks.theodolite.benchmarks.uc1.commons;
+
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * Converts an {@link ActivePowerRecord} to the type required by a database.
+ *
+ * @param <T> Type required by the database.
+ */
+@FunctionalInterface
+public interface RecordConverter<T> {
+
+  T convert(ActivePowerRecord record);
+
+}
diff --git a/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/logger/JsonConverter.java b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/logger/JsonConverter.java
new file mode 100644
index 0000000000000000000000000000000000000000..f9974affb7bf57fc63e9bfe8ba92fd056da9a97b
--- /dev/null
+++ b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/logger/JsonConverter.java
@@ -0,0 +1,22 @@
+package rocks.theodolite.benchmarks.uc1.commons.logger;
+
+import com.google.gson.Gson;
+import java.io.Serializable;
+import rocks.theodolite.benchmarks.uc1.commons.RecordConverter;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * {@link RecordConverter} that converts {@link ActivePowerRecord}s to JSON strings.
+ */
+public class JsonConverter implements RecordConverter<String>, Serializable {
+
+  private static final long serialVersionUID = -5263671231838353748L; // NOPMD
+
+  private static final Gson GSON = new Gson();
+
+  @Override
+  public String convert(final ActivePowerRecord activePowerRecord) {
+    return GSON.toJson(activePowerRecord);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/logger/LogWriter.java b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/logger/LogWriter.java
new file mode 100644
index 0000000000000000000000000000000000000000..d606a6dffd01257b308bf2afebc3088b52793ccf
--- /dev/null
+++ b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/logger/LogWriter.java
@@ -0,0 +1,22 @@
+package rocks.theodolite.benchmarks.uc1.commons.logger;
+
+import java.io.Serializable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import rocks.theodolite.benchmarks.uc1.commons.DatabaseWriter;
+
+/**
+ * Writes string records to a {@link Logger}.
+ */
+public class LogWriter implements DatabaseWriter<String>, Serializable {
+
+  private static final long serialVersionUID = -5263671231838353749L; // NOPMD
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(LogWriter.class);
+
+  @Override
+  public void write(final String string) {
+    LOGGER.info("Record: {}", string);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/logger/LogWriterFactory.java b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/logger/LogWriterFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..305ed933ba3e0d885de9c65aacc6ace8a0884621
--- /dev/null
+++ b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/logger/LogWriterFactory.java
@@ -0,0 +1,18 @@
+package rocks.theodolite.benchmarks.uc1.commons.logger;
+
+import org.slf4j.Logger;
+import rocks.theodolite.benchmarks.uc1.commons.DatabaseAdapter;
+
+/**
+ * Provides factory methods for creating a dummy {@link DatabaseAdapter} writing records as logs
+ * using a SLF4J {@link Logger}.
+ */
+public final class LogWriterFactory {
+
+  private LogWriterFactory() {}
+
+  public static DatabaseAdapter<String> forJson() {
+    return DatabaseAdapter.from(new JsonConverter(), new LogWriter());
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-flink/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc1-flink/.settings/org.eclipse.jdt.ui.prefs
index fa98ca63d77bdee891150bd6713f70197a75cefc..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc1-flink/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc1-flink/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,25 +12,72 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
 cleanup.remove_redundant_semicolons=true
@@ -37,6 +85,7 @@ cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,27 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -79,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -114,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc1-flink/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc1-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/uc1-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/uc1-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/uc1-flink/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc1-flink/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/uc1-flink/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/uc1-flink/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc1-flink/Dockerfile b/theodolite-benchmarks/uc1-flink/Dockerfile
index 795b9e343a03cf0209e1625f5cbc3d45dcb77cda..fdaecd661e86275d670423351664e54221ce33cc 100644
--- a/theodolite-benchmarks/uc1-flink/Dockerfile
+++ b/theodolite-benchmarks/uc1-flink/Dockerfile
@@ -1,3 +1,3 @@
-FROM flink:1.12-scala_2.12-java11
+FROM flink:1.13-java11
 
 ADD build/libs/uc1-flink-all.jar /opt/flink/usrlib/artifacts/uc1-flink-all.jar
diff --git a/theodolite-benchmarks/uc1-flink/build.gradle b/theodolite-benchmarks/uc1-flink/build.gradle
index 8a2a359c4840e67581f7bc24f1544ff519f82525..4eb96987e7974259f693d37d2f063243a3d0bb6d 100644
--- a/theodolite-benchmarks/uc1-flink/build.gradle
+++ b/theodolite-benchmarks/uc1-flink/build.gradle
@@ -2,4 +2,8 @@ plugins {
   id 'theodolite.flink'
 }
 
-mainClassName = "theodolite.uc1.application.HistoryServiceFlinkJob"
+dependencies {
+    implementation project(':uc1-commons')
+}
+
+mainClassName = "rocks.theodolite.benchmarks.uc1.flink.HistoryServiceFlinkJob"
diff --git a/theodolite-benchmarks/uc1-flink/src/main/java/theodolite/uc1/application/ConfigurationKeys.java b/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/ConfigurationKeys.java
similarity index 93%
rename from theodolite-benchmarks/uc1-flink/src/main/java/theodolite/uc1/application/ConfigurationKeys.java
rename to theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/ConfigurationKeys.java
index 382525cfe75f82dbbe8fbcc85308b0e7788a43bc..d2235e0693abe8f5f45899eb03bfbefec51526d5 100644
--- a/theodolite-benchmarks/uc1-flink/src/main/java/theodolite/uc1/application/ConfigurationKeys.java
+++ b/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/ConfigurationKeys.java
@@ -1,4 +1,4 @@
-package theodolite.uc1.application;
+package rocks.theodolite.benchmarks.uc1.flink;
 
 /**
  * Keys to access configuration parameters.
diff --git a/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/ConverterAdapter.java b/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/ConverterAdapter.java
new file mode 100644
index 0000000000000000000000000000000000000000..064b8afbb03dc16262ca7fcf90a0fdd8af4419a9
--- /dev/null
+++ b/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/ConverterAdapter.java
@@ -0,0 +1,27 @@
+package rocks.theodolite.benchmarks.uc1.flink;
+
+import org.apache.flink.api.common.functions.MapFunction;
+import rocks.theodolite.benchmarks.uc1.commons.RecordConverter;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * {@link MapFunction} which wraps a {@link RecordConverter} to be used with Flink.
+ *
+ * @param <T> type the {@link RecordConverter} is associated with.
+ */
+public class ConverterAdapter<T> implements MapFunction<ActivePowerRecord, T> {
+
+  private static final long serialVersionUID = -5263671231838353747L; // NOPMD
+
+  private final RecordConverter<T> recordConverter;
+
+  public ConverterAdapter(final RecordConverter<T> recordConverter) {
+    this.recordConverter = recordConverter;
+  }
+
+  @Override
+  public T map(final ActivePowerRecord record) throws Exception {
+    return this.recordConverter.convert(record);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-flink/src/main/java/theodolite/uc1/application/HistoryServiceFlinkJob.java b/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/HistoryServiceFlinkJob.java
similarity index 84%
rename from theodolite-benchmarks/uc1-flink/src/main/java/theodolite/uc1/application/HistoryServiceFlinkJob.java
rename to theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/HistoryServiceFlinkJob.java
index 0cb132e526486e71409736b843dd25bdfa52da4a..d674effac653cb1613a1b218f381ec3c6c910673 100644
--- a/theodolite-benchmarks/uc1-flink/src/main/java/theodolite/uc1/application/HistoryServiceFlinkJob.java
+++ b/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/HistoryServiceFlinkJob.java
@@ -1,4 +1,4 @@
-package theodolite.uc1.application;
+package rocks.theodolite.benchmarks.uc1.flink;
 
 import org.apache.commons.configuration2.Configuration;
 import org.apache.flink.api.common.typeinfo.Types;
@@ -7,7 +7,9 @@ import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
 import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import theodolite.commons.flink.KafkaConnectorFactory;
+import rocks.theodolite.benchmarks.commons.flink.KafkaConnectorFactory;
+import rocks.theodolite.benchmarks.uc1.commons.DatabaseAdapter;
+import rocks.theodolite.benchmarks.uc1.commons.logger.LogWriterFactory;
 import titan.ccp.common.configuration.ServiceConfigurations;
 import titan.ccp.model.records.ActivePowerRecord;
 
@@ -22,6 +24,8 @@ public final class HistoryServiceFlinkJob {
   private final StreamExecutionEnvironment env;
   private final String applicationId;
 
+  private final DatabaseAdapter<String> databaseAdapter = LogWriterFactory.forJson();
+
   /**
    * Create a new instance of the {@link HistoryServiceFlinkJob}.
    */
@@ -69,9 +73,10 @@ public final class HistoryServiceFlinkJob {
 
     stream
         // .rebalance()
-        .map(new GsonMapper())
-        .flatMap((record, c) -> LOGGER.info("Record: {}", record))
-        .returns(Types.GENERIC(Object.class)); // Will never be used
+        .map(new ConverterAdapter<>(this.databaseAdapter.getRecordConverter()))
+        .returns(Types.STRING)
+        .flatMap(new WriterAdapter<>(this.databaseAdapter.getDatabaseWriter()))
+        .returns(Types.VOID); // Will never be used
   }
 
   /**
diff --git a/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/WriterAdapter.java b/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/WriterAdapter.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ead8d8c63c10b8057832e72c93c34b583eda838
--- /dev/null
+++ b/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/WriterAdapter.java
@@ -0,0 +1,28 @@
+package rocks.theodolite.benchmarks.uc1.flink;
+
+import org.apache.flink.api.common.functions.FlatMapFunction;
+import org.apache.flink.util.Collector;
+import rocks.theodolite.benchmarks.uc1.commons.DatabaseAdapter;
+import rocks.theodolite.benchmarks.uc1.commons.DatabaseWriter;
+
+/**
+ * {@link FlatMapFunction} which wraps a {@link DatabaseAdapter} to be used with Flink.
+ *
+ * @param <T> type the {@link DatabaseWriter} is associated with.
+ */
+public class WriterAdapter<T> implements FlatMapFunction<T, Void> {
+
+  private static final long serialVersionUID = -5263671231838353747L; // NOPMD
+
+  private final DatabaseWriter<T> databaseWriter;
+
+  public WriterAdapter(final DatabaseWriter<T> databaseWriter) {
+    this.databaseWriter = databaseWriter;
+  }
+
+  @Override
+  public void flatMap(final T value, final Collector<Void> out) throws Exception {
+    this.databaseWriter.write(value);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-flink/src/main/java/theodolite/uc1/application/GsonMapper.java b/theodolite-benchmarks/uc1-flink/src/main/java/theodolite/uc1/application/GsonMapper.java
deleted file mode 100644
index 831db7fe63be6529e6b7ba299dca92b138ff7d13..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc1-flink/src/main/java/theodolite/uc1/application/GsonMapper.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package theodolite.uc1.application;
-
-import com.google.gson.Gson;
-import org.apache.flink.api.common.functions.MapFunction;
-import titan.ccp.model.records.ActivePowerRecord;
-
-/**
- * {@link MapFunction} which maps {@link ActivePowerRecord}s to their representation as JSON
- * strings.
- */
-public class GsonMapper implements MapFunction<ActivePowerRecord, String> {
-
-  private static final long serialVersionUID = -5263671231838353747L; // NOPMD
-
-  private static final Gson GSON = new Gson();
-
-  @Override
-  public String map(final ActivePowerRecord value) throws Exception {
-    return GSON.toJson(value);
-  }
-
-}
diff --git a/theodolite-benchmarks/uc1-hazelcastjet/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc1-hazelcastjet/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/uc1-hazelcastjet/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc1-hazelcastjet/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc1-hazelcastjet/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc1-hazelcastjet/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc1-hazelcastjet/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc1-hazelcastjet/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc1-hazelcastjet/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc1-hazelcastjet/Dockerfile b/theodolite-benchmarks/uc1-hazelcastjet/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..7a0fcf7c5f61bed97c9a1e6d455164c64930c4fe
--- /dev/null
+++ b/theodolite-benchmarks/uc1-hazelcastjet/Dockerfile
@@ -0,0 +1,7 @@
+FROM openjdk:11-slim
+
+ADD build/distributions/uc1-hazelcastjet.tar /
+
+
+CMD  JAVA_OPTS="$JAVA_OPTS -Dorg.slf4j.simpleLogger.defaultLogLevel=$LOG_LEVEL" \
+     /uc1-hazelcastjet/bin/uc1-hazelcastjet
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc1-hazelcastjet/build.gradle b/theodolite-benchmarks/uc1-hazelcastjet/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..cac5ad9f6f12b62389236decbe75fbec01050071
--- /dev/null
+++ b/theodolite-benchmarks/uc1-hazelcastjet/build.gradle
@@ -0,0 +1,9 @@
+plugins {
+  id 'theodolite.hazelcastjet'
+}
+
+dependencies {
+    implementation project(':uc1-commons')
+}
+
+mainClassName = "rocks.theodolite.benchmarks.uc1.hazelcastjet.HistoryService"
diff --git a/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/HistoryService.java b/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/HistoryService.java
new file mode 100644
index 0000000000000000000000000000000000000000..83848261318b2e90d19f28d9ab53fdc2cf678279
--- /dev/null
+++ b/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/HistoryService.java
@@ -0,0 +1,64 @@
+package rocks.theodolite.benchmarks.uc1.hazelcastjet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A microservice that manages the history and, therefore, stores and aggregates incoming
+ * measurements.
+ */
+public class HistoryService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(HistoryService.class);
+
+  // Hazelcast settings (default)
+  private static final String HZ_KUBERNETES_SERVICE_DNS_KEY = "service-dns";
+  private static final String BOOTSTRAP_SERVER_DEFAULT = "localhost:5701";
+
+  // Kafka settings (default)
+  private static final String KAFKA_BOOTSTRAP_DEFAULT = "localhost:9092";
+  private static final String SCHEMA_REGISTRY_URL_DEFAULT = "http://localhost:8081";
+  private static final String KAFKA_TOPIC_DEFAULT = "input";
+
+  // Job name (default)
+  private static final String JOB_NAME = "uc1-hazelcastjet";
+
+
+  /**
+   * Entrypoint for UC1 using Gradle Run.
+   */
+  public static void main(final String[] args) {
+    final HistoryService uc1HistoryService = new HistoryService();
+    try {
+      uc1HistoryService.run();
+    } catch (final Exception e) { // NOPMD
+      LOGGER.error("ABORT MISSION!: {}", e);
+    }
+  }
+
+  /**
+   * Start a UC1 service.
+   *
+   * @throws Exception This Exception occurs if the Uc1HazelcastJetFactory is used in the wrong way.
+   *         Detailed data is provided once an Exception occurs.
+   */
+  public void run() throws Exception { // NOPMD
+    this.createHazelcastJetApplication();
+  }
+
+  /**
+   * Creates a Hazelcast Jet Application for UC1 using the Uc1HazelcastJetFactory.
+   *
+   * @throws Exception This Exception occurs if the Uc1HazelcastJetFactory is used in the wrong way.
+   *         Detailed data is provided once an Exception occurs.
+   */
+  private void createHazelcastJetApplication() throws Exception { // NOPMD
+    new Uc1HazelcastJetFactory()
+        .setPropertiesFromEnv(KAFKA_BOOTSTRAP_DEFAULT, SCHEMA_REGISTRY_URL_DEFAULT,JOB_NAME)
+        .setKafkaInputTopicFromEnv(KAFKA_TOPIC_DEFAULT)
+        .buildUc1Pipeline()
+        .buildUc1JetInstanceFromEnv(LOGGER, BOOTSTRAP_SERVER_DEFAULT, HZ_KUBERNETES_SERVICE_DNS_KEY)
+        .runUc1Job(JOB_NAME);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/Uc1HazelcastJetFactory.java b/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/Uc1HazelcastJetFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..4a5c5dead14e606847dc5e2ac3c95414d9f611b3
--- /dev/null
+++ b/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/Uc1HazelcastJetFactory.java
@@ -0,0 +1,178 @@
+package rocks.theodolite.benchmarks.uc1.hazelcastjet;
+
+import com.hazelcast.jet.JetInstance;
+import com.hazelcast.jet.config.JobConfig;
+import com.hazelcast.jet.pipeline.Pipeline;
+import io.confluent.kafka.serializers.KafkaAvroDeserializer;
+import java.util.Objects;
+import java.util.Properties;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import org.slf4j.Logger;
+import rocks.theodolite.benchmarks.commons.hazelcastjet.ConfigurationKeys;
+import rocks.theodolite.benchmarks.commons.hazelcastjet.JetInstanceBuilder;
+import rocks.theodolite.benchmarks.commons.hazelcastjet.KafkaPropertiesBuilder;
+
+/**
+ * A Hazelcast Jet factory which can build a Hazelcast Jet Instance and Pipeline for the UC1
+ * benchmark and lets you start the Hazelcast Jet job. The JetInstance can be built directly as the
+ * Hazelcast Config is managed internally. In order to build the Pipeline, you first have to build
+ * the Properties and set the input topic which can be done using internal functions of this
+ * factory. Outside data only refers to custom values or default values in case data of the
+ * environment cannot the fetched.
+ */
+public class Uc1HazelcastJetFactory {
+
+  // Information per History Service
+  private Properties kafkaPropertiesForPipeline;
+  private String kafkaInputTopic;
+  private JetInstance uc1JetInstance;
+  private Pipeline uc1JetPipeline;
+
+  /////////////////////////////////////
+  // Layer 1 - Hazelcast Jet Run Job //
+  /////////////////////////////////////
+
+  /**
+   * Needs a JetInstance and Pipeline defined in this factors. Adds the pipeline to the existing
+   * JetInstance as a job.
+   *
+   * @param jobName The name of the job.
+   */
+  public void runUc1Job(final String jobName) {
+
+    // Check if a Jet Instance for UC1 is set.
+    if (this.uc1JetInstance == null) {
+      throw new IllegalStateException("Jet Instance is not set! "
+          + "Cannot start a hazelcast jet job for UC1.");
+    }
+
+    // Check if a Pipeline for UC1 is set.
+    if (this.uc1JetPipeline == null) {
+      throw new IllegalStateException(
+          "Hazelcast Pipeline is not set! Cannot start a hazelcast jet job for UC1.");
+    }
+
+    // Adds the job name and joins a job to the JetInstance defined in this factory
+    final JobConfig jobConfig = new JobConfig();
+    jobConfig.setName(jobName);
+    this.uc1JetInstance.newJobIfAbsent(this.uc1JetPipeline, jobConfig).join();
+  }
+
+  /////////////
+  // Layer 2 //
+  /////////////
+
+  /**
+   * Build a Hazelcast JetInstance used to run a job on.
+   *
+   * @param logger The logger specified for this JetInstance.
+   * @param bootstrapServerDefault Default bootstrap server in case no value can be derived from the
+   *        environment.
+   * @param hzKubernetesServiceDnsKey The kubernetes service dns key.
+   * @return A Uc1HazelcastJetFactory containing a set JetInstance.
+   */
+  public Uc1HazelcastJetFactory buildUc1JetInstanceFromEnv(final Logger logger,
+      final String bootstrapServerDefault,
+      final String hzKubernetesServiceDnsKey) {
+    this.uc1JetInstance = new JetInstanceBuilder()
+        .setConfigFromEnv(logger, bootstrapServerDefault, hzKubernetesServiceDnsKey)
+        .build();
+    return this;
+  }
+
+  /**
+   * Builds a Hazelcast Jet pipeline used for a JetInstance to run it as a job on. Needs the input
+   * topic and kafka properties defined in this factory beforehand.
+   *
+   * @return A Uc1HazelcastJetFactory containg a set pipeline.
+   */
+  public Uc1HazelcastJetFactory buildUc1Pipeline() {
+
+    // Check if Properties for the Kafka Input are set.
+    if (this.kafkaPropertiesForPipeline == null) {
+      throw new IllegalStateException(
+          "Kafka Properties for pipeline not set! Cannot build pipeline.");
+    }
+
+    // Check if the Kafka input topic is set.
+    if (this.kafkaInputTopic == null) {
+      throw new IllegalStateException("Kafka input topic for pipeline not set! "
+          + "Cannot build pipeline.");
+    }
+
+    // Build Pipeline Using the pipelineBuilder
+    final Uc1PipelineBuilder pipeBuilder = new Uc1PipelineBuilder();
+    this.uc1JetPipeline =
+        pipeBuilder.build(this.kafkaPropertiesForPipeline, this.kafkaInputTopic);
+    // Return Uc1HazelcastJetBuilder factory
+    return this;
+  }
+
+  /////////////
+  // Layer 3 //
+  /////////////
+
+  /**
+   * Sets kafka properties for pipeline used in this builder.
+   *
+   * @param kafkaProperties A propeties object containing necessary values used for the hazelcst jet
+   *        kafka connection.
+   * @return The Uc1HazelcastJetBuilder factory with set kafkaPropertiesForPipeline.
+   */
+  public Uc1HazelcastJetFactory setCustomProperties(final Properties kafkaProperties) { // NOPMD
+    this.kafkaPropertiesForPipeline = kafkaProperties;
+    return this;
+  }
+
+  /**
+   * Sets kafka properties for pipeline used in this builder using environment variables.
+   *
+   * @param bootstrapServersDefault Default Bootstrap server in the case that no bootstrap server
+   *        can be fetched from the environment.
+   * @param schemaRegistryUrlDefault Default schema registry url in the case that no schema registry
+   *        url can be fetched from the environment.
+   * @return The Uc1HazelcastJetBuilder factory with set kafkaPropertiesForPipeline.
+   */
+  public Uc1HazelcastJetFactory setPropertiesFromEnv(final String bootstrapServersDefault, // NOPMD
+                                                     final String schemaRegistryUrlDefault,
+                                                     final String jobName) {
+    // Use KafkaPropertiesBuilder to build a properties object used for kafka
+    final KafkaPropertiesBuilder propsBuilder = new KafkaPropertiesBuilder();
+    final Properties kafkaProps =
+        propsBuilder.buildKafkaInputReadPropsFromEnv(bootstrapServersDefault,
+            schemaRegistryUrlDefault,
+            jobName,
+            StringDeserializer.class.getCanonicalName(),
+            KafkaAvroDeserializer.class.getCanonicalName());
+    this.kafkaPropertiesForPipeline = kafkaProps;
+    return this;
+  }
+
+  /**
+   * Sets the kafka input topic for the pipeline used in this builder.
+   *
+   * @param inputTopic The kafka topic used as the pipeline input.
+   * @return A Uc1HazelcastJetBuilder factory with a set kafkaInputTopic.
+   */
+  public Uc1HazelcastJetFactory setCustomKafkaInputTopic(final String inputTopic) { // NOPMD
+    this.kafkaInputTopic = inputTopic;
+    return this;
+  }
+
+  /**
+   * Sets the kafka input topic for the pipeline used in this builder using environment variables.
+   *
+   * @param defaultInputTopic The default kafka input topic used if no topic is specified by the
+   *        environment.
+   * @return A Uc1HazelcastJetBuilder factory with a set kafkaInputTopic.
+   */
+  public Uc1HazelcastJetFactory setKafkaInputTopicFromEnv(final String defaultInputTopic) { // NOPMD
+    this.kafkaInputTopic = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_INPUT_TOPIC),
+        defaultInputTopic);
+    return this;
+  }
+
+
+
+}
diff --git a/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/Uc1PipelineBuilder.java b/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/Uc1PipelineBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..c02ea1e7ea7fb3f27bdbf818248678011a93f6a2
--- /dev/null
+++ b/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/Uc1PipelineBuilder.java
@@ -0,0 +1,82 @@
+package rocks.theodolite.benchmarks.uc1.hazelcastjet;
+
+import static com.hazelcast.jet.pipeline.SinkBuilder.sinkBuilder;
+
+import com.hazelcast.jet.kafka.KafkaSources;
+import com.hazelcast.jet.pipeline.Pipeline;
+import com.hazelcast.jet.pipeline.Sink;
+import com.hazelcast.jet.pipeline.StreamSource;
+import com.hazelcast.jet.pipeline.StreamStage;
+import java.util.Map.Entry;
+import java.util.Properties;
+import rocks.theodolite.benchmarks.uc1.commons.DatabaseAdapter;
+import rocks.theodolite.benchmarks.uc1.commons.DatabaseWriter;
+import rocks.theodolite.benchmarks.uc1.commons.logger.LogWriterFactory;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * Builder to build a HazelcastJet Pipeline for UC1 which can be used for stream processing using
+ * Hazelcast Jet.
+ */
+public class Uc1PipelineBuilder {
+
+  private final DatabaseAdapter<String> databaseAdapter = LogWriterFactory.forJson();
+
+  /**
+   * Builds a pipeline which can be used for stream processing using Hazelcast Jet.
+   *
+   * @param kafkaPropsForPipeline Properties object containing the necessary Kafka attributes.
+   * @param kafkaInputTopic The name of the input topic used for the pipeline.
+   * @return A Hazelcast Jet pipeline which processes data for Uc1.
+   */
+  public Pipeline build(final Properties kafkaPropsForPipeline, final String kafkaInputTopic) {
+
+    // Define a new pipeline
+    final Pipeline pipe = Pipeline.create();
+
+    // Define the Kafka Source
+    final StreamSource<Entry<String, ActivePowerRecord>> kafkaSource =
+        KafkaSources.<String, ActivePowerRecord>kafka(kafkaPropsForPipeline, kafkaInputTopic);
+
+    // Extend UC1 topology to the pipeline
+    final StreamStage<String> uc1TopologyProduct = this.extendUc1Topology(pipe, kafkaSource);
+
+    // Add Sink: Logger
+    // Do not refactor this to just use the call
+    // (There is a problem with static calls in functions in hazelcastjet)
+    final DatabaseWriter<String> writer = this.databaseAdapter.getDatabaseWriter();
+    final Sink<String> sink = sinkBuilder(
+        "Sink into database", x -> writer)
+        .<String>receiveFn(DatabaseWriter::write)
+        .build();
+
+    uc1TopologyProduct.writeTo(sink);
+
+    return pipe;
+  }
+
+  /**
+   * Extends to a blank Hazelcast Jet Pipeline the UC1 topology defines by Theodolite.
+   *
+   * <p>
+   * UC1 takes {@code Entry<String,ActivePowerRecord>} objects and turns them into JSON strings
+   * using GSON.
+   * </p>
+   *
+   * @param pipe The blank hazelcast jet pipeline to extend the logic to.
+   * @param source A streaming source to fetch data from.
+   * @return A {@code StreamStage<String>} with the above definition of the String. It can be used
+   *         to be further modified or directly be written into a sink.
+   */
+  public StreamStage<String> extendUc1Topology(final Pipeline pipe,
+      final StreamSource<Entry<String, ActivePowerRecord>> source) {
+
+    // Build the pipeline topology
+    return pipe.readFrom(source)
+        .withNativeTimestamps(0)
+        .setLocalParallelism(1)
+        .setName("Convert content")
+        .map(Entry::getValue)
+        .map(this.databaseAdapter.getRecordConverter()::convert);
+  }
+}
diff --git a/theodolite-benchmarks/uc1-hazelcastjet/src/main/resources/META-INF/application.properties b/theodolite-benchmarks/uc1-hazelcastjet/src/main/resources/META-INF/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..e3371cc87e20e85e6e8c327955537e6e49dab86e
--- /dev/null
+++ b/theodolite-benchmarks/uc1-hazelcastjet/src/main/resources/META-INF/application.properties
@@ -0,0 +1,8 @@
+application.name=theodolite-uc1-application
+application.version=0.0.1
+
+kafka.bootstrap.servers=localhost:9092
+kafka.input.topic=input
+
+schema.registry.url=http://localhost:8081
+
diff --git a/theodolite-benchmarks/uc1-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc1/hazelcast/Uc1PipelineTest.java b/theodolite-benchmarks/uc1-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc1/hazelcast/Uc1PipelineTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..525327ddbcdcddb6cf1bfe4e2d6be62d3384fc0c
--- /dev/null
+++ b/theodolite-benchmarks/uc1-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc1/hazelcast/Uc1PipelineTest.java
@@ -0,0 +1,152 @@
+package rocks.theodolite.benchmarks.uc1.hazelcast;
+
+import com.hazelcast.jet.Jet;
+import com.hazelcast.jet.JetInstance;
+import com.hazelcast.jet.config.JetConfig;
+import com.hazelcast.jet.core.JetTestSupport;
+import com.hazelcast.jet.pipeline.Pipeline;
+import com.hazelcast.jet.pipeline.Sink;
+import com.hazelcast.jet.pipeline.StreamSource;
+import com.hazelcast.jet.pipeline.StreamStage;
+import com.hazelcast.jet.pipeline.test.AssertionCompletedException;
+import com.hazelcast.jet.pipeline.test.Assertions;
+import com.hazelcast.jet.pipeline.test.TestSources;
+import com.hazelcast.jet.test.SerialTest;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.CompletionException;
+import com.hazelcast.logging.ILogger;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.slf4j.Logger;
+import rocks.theodolite.benchmarks.uc1.commons.DatabaseAdapter;
+import rocks.theodolite.benchmarks.uc1.commons.DatabaseWriter;
+import rocks.theodolite.benchmarks.uc1.commons.logger.LogWriterFactory;
+import rocks.theodolite.benchmarks.uc1.hazelcastjet.Uc1PipelineBuilder;
+import titan.ccp.model.records.ActivePowerRecord;
+
+import static com.hazelcast.jet.pipeline.SinkBuilder.sinkBuilder;
+import static com.hazelcast.logging.Logger.getLogger;
+
+/**
+ * Test methods for the Hazelcast Jet Implementation of UC1.
+ */
+@Category(SerialTest.class)
+public class Uc1PipelineTest extends JetTestSupport {
+
+  private JetInstance testInstance = null;
+  private Pipeline testPipeline = null;
+  private StreamStage<String> uc1Topology = null;
+
+  // Standart Logger
+  private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(Uc1PipelineTest.class);
+  // HazelcastJet Logger
+  private static final ILogger logger =  getLogger(Uc1PipelineTest.class);
+
+  private final DatabaseAdapter<String> databaseAdapter = LogWriterFactory.forJson();
+
+  /**
+   * Creates the JetInstance, defines a new Hazelcast Jet Pipeline and extends the UC1 topology.
+   * Allows for quick extension of tests.
+   */
+  @Before
+  public void buildUc1Pipeline() {
+
+    this.logger.info("Hazelcast Logger");
+    LOGGER.info("Standard Logger");
+
+
+    // Setup Configuration
+    final int testItemsPerSecond = 1;
+    final String testSensorName = "TEST_SENSOR";
+    final Double testValueInW = 10.0;
+
+    // Create mock jet instance with configuration
+    final String testClusterName = randomName();
+    final JetConfig testJetConfig = new JetConfig();
+//    testJetConfig.setProperty( "hazelcast.logging.type", "slf4j" );
+    testJetConfig.getHazelcastConfig().setClusterName(testClusterName);
+    this.testInstance = createJetMember(testJetConfig);
+
+
+    // Create a test source
+    final StreamSource<Entry<String, ActivePowerRecord>> testSource =
+        TestSources.itemStream(testItemsPerSecond, (timestamp, item) -> {
+          final ActivePowerRecord testRecord =
+              new ActivePowerRecord(testSensorName, timestamp, testValueInW);
+          final Entry<String, ActivePowerRecord> testEntry =
+              Map.entry(testSensorName, testRecord);
+          return testEntry;
+        });
+
+    // Create pipeline to test
+    final Uc1PipelineBuilder pipelineBuilder = new Uc1PipelineBuilder();
+    this.testPipeline = Pipeline.create();
+    this.uc1Topology =
+        pipelineBuilder.extendUc1Topology(this.testPipeline, testSource);
+
+    // Create DatabaseWriter sink
+    final DatabaseWriter<String> adapter = this.databaseAdapter.getDatabaseWriter();
+    final Sink<String> sink = sinkBuilder(
+        "database-sink", x -> adapter)
+        .<String>receiveFn(DatabaseWriter::write)
+        .build();
+
+//    Map Stage, can be used instead of sink
+//    StreamStage<String> log = uc1Topology.map(s -> {
+//        LOGGER.info(s);
+//        return s;
+//    });
+//    log.writeTo(sink);
+
+    //apply sink
+    this.uc1Topology.writeTo(sink);
+  }
+
+  /**
+   * UC1 Pipeline test to check if items are passed through at an acceptable rate.
+   */
+  @Test
+  public void test1Uc1PipelineElements() {
+
+    // Assertion Configuration
+    final int assertTimeoutSeconds = 6;
+    final int assertCollectedItems = 5;
+
+    LOGGER.info("Pipeline build successfully, starting test");
+
+    // Assertion
+    this.uc1Topology.apply(Assertions.assertCollectedEventually(assertTimeoutSeconds,
+        collection -> {
+      //print the newest Record
+//      LOGGER.info(collection.get(collection.size()-1));
+
+          // Run pipeline until 5th item
+          Assert.assertTrue("Not enough data arrived in the end",
+              collection.size() >= assertCollectedItems);
+        }));
+
+    // Test the UC1 Pipeline Recreation
+    try {
+      this.testInstance.newJob(this.testPipeline).join();
+      Assert.fail("Job should have completed with an AssertionCompletedException, "
+          + "but completed normally");
+    } catch (final CompletionException e) {
+      final String errorMsg = e.getCause().getMessage();
+      Assert.assertTrue(
+          "Job was expected to complete with AssertionCompletedException, but completed with: "
+              + e.getCause(),
+          errorMsg.contains(AssertionCompletedException.class.getName()));
+    }
+  }
+
+  @After
+  public void after() {
+    // Shuts down all running Jet Instances
+    Jet.shutdownAll();
+  }
+
+}
diff --git a/theodolite-benchmarks/uc1-kstreams/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc1-kstreams/.settings/org.eclipse.jdt.ui.prefs
index fa98ca63d77bdee891150bd6713f70197a75cefc..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc1-kstreams/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc1-kstreams/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,25 +12,72 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
 cleanup.remove_redundant_semicolons=true
@@ -37,6 +85,7 @@ cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,27 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -79,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -114,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc1-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc1-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/uc1-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/uc1-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/uc1-kstreams/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc1-kstreams/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/uc1-kstreams/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/uc1-kstreams/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc1-kstreams/build.gradle b/theodolite-benchmarks/uc1-kstreams/build.gradle
index 74cfb450ec80759f60582c25ab844e3398d5bf02..15fd13dcde355974eb77dea61e32891592d27ac2 100644
--- a/theodolite-benchmarks/uc1-kstreams/build.gradle
+++ b/theodolite-benchmarks/uc1-kstreams/build.gradle
@@ -2,4 +2,8 @@ plugins {
   id 'theodolite.kstreams'
 }
 
-mainClassName = "theodolite.uc1.application.HistoryService"
+dependencies {
+    implementation project(':uc1-commons')
+}
+
+mainClassName = "rocks.theodolite.benchmarks.uc1.kstreams.HistoryService"
diff --git a/theodolite-benchmarks/uc1-kstreams/src/main/java/theodolite/uc1/application/HistoryService.java b/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/HistoryService.java
similarity index 91%
rename from theodolite-benchmarks/uc1-kstreams/src/main/java/theodolite/uc1/application/HistoryService.java
rename to theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/HistoryService.java
index f0d8062a2442181507c0bef990b73e0e9cf4a372..0a2a1bec7c3515f903905efeb07e717a46e329ea 100644
--- a/theodolite-benchmarks/uc1-kstreams/src/main/java/theodolite/uc1/application/HistoryService.java
+++ b/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/HistoryService.java
@@ -1,9 +1,8 @@
-package theodolite.uc1.application;
+package rocks.theodolite.benchmarks.uc1.kstreams;
 
 import java.util.concurrent.CompletableFuture;
 import org.apache.commons.configuration2.Configuration;
 import org.apache.kafka.streams.KafkaStreams;
-import theodolite.uc1.streamprocessing.Uc1KafkaStreamsBuilder;
 import titan.ccp.common.configuration.ServiceConfigurations;
 
 /**
diff --git a/theodolite-benchmarks/uc1-kstreams/src/main/java/theodolite/uc1/streamprocessing/TopologyBuilder.java b/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/TopologyBuilder.java
similarity index 74%
rename from theodolite-benchmarks/uc1-kstreams/src/main/java/theodolite/uc1/streamprocessing/TopologyBuilder.java
rename to theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/TopologyBuilder.java
index 427a838f45f6807ede00dcb68ebf8c5580f28ce6..944e449c4693dc7c234844c97567d7f9f048cf3b 100644
--- a/theodolite-benchmarks/uc1-kstreams/src/main/java/theodolite/uc1/streamprocessing/TopologyBuilder.java
+++ b/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/TopologyBuilder.java
@@ -1,13 +1,12 @@
-package theodolite.uc1.streamprocessing;
+package rocks.theodolite.benchmarks.uc1.kstreams;
 
-import com.google.gson.Gson;
 import java.util.Properties;
 import org.apache.kafka.common.serialization.Serdes;
 import org.apache.kafka.streams.StreamsBuilder;
 import org.apache.kafka.streams.Topology;
 import org.apache.kafka.streams.kstream.Consumed;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import rocks.theodolite.benchmarks.uc1.commons.DatabaseAdapter;
+import rocks.theodolite.benchmarks.uc1.commons.logger.LogWriterFactory;
 import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory;
 import titan.ccp.model.records.ActivePowerRecord;
 
@@ -16,12 +15,11 @@ import titan.ccp.model.records.ActivePowerRecord;
  */
 public class TopologyBuilder {
 
-  private static final Logger LOGGER = LoggerFactory.getLogger(TopologyBuilder.class);
-  private static final Gson GSON = new Gson();
-
   private final String inputTopic;
   private final SchemaRegistryAvroSerdeFactory srAvroSerdeFactory;
 
+  private final DatabaseAdapter<String> databaseAdapter = LogWriterFactory.forJson();
+
   private final StreamsBuilder builder = new StreamsBuilder();
 
 
@@ -42,8 +40,8 @@ public class TopologyBuilder {
         .stream(this.inputTopic, Consumed.with(
             Serdes.String(),
             this.srAvroSerdeFactory.<ActivePowerRecord>forValues()))
-        .mapValues(v -> GSON.toJson(v))
-        .foreach((k, record) -> LOGGER.info("Record: {}", record));
+        .mapValues(this.databaseAdapter.getRecordConverter()::convert)
+        .foreach((k, record) -> this.databaseAdapter.getDatabaseWriter().write(record));
 
     return this.builder.build(properties);
   }
diff --git a/theodolite-benchmarks/uc1-kstreams/src/main/java/theodolite/uc1/streamprocessing/Uc1KafkaStreamsBuilder.java b/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/Uc1KafkaStreamsBuilder.java
similarity index 85%
rename from theodolite-benchmarks/uc1-kstreams/src/main/java/theodolite/uc1/streamprocessing/Uc1KafkaStreamsBuilder.java
rename to theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/Uc1KafkaStreamsBuilder.java
index cc39bb04623c06a4d41cb2c695804ed41818a67c..a1e9c4d78d0f340273fb3db944ba96913c8d0b13 100644
--- a/theodolite-benchmarks/uc1-kstreams/src/main/java/theodolite/uc1/streamprocessing/Uc1KafkaStreamsBuilder.java
+++ b/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/Uc1KafkaStreamsBuilder.java
@@ -1,10 +1,10 @@
-package theodolite.uc1.streamprocessing;
+package rocks.theodolite.benchmarks.uc1.kstreams;
 
 import java.util.Objects;
 import java.util.Properties;
 import org.apache.commons.configuration2.Configuration;
 import org.apache.kafka.streams.Topology;
-import theodolite.commons.kafkastreams.KafkaStreamsBuilder;
+import rocks.theodolite.benchmarks.commons.kstreams.KafkaStreamsBuilder;
 import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory;
 
 /**
diff --git a/theodolite-benchmarks/uc1-load-generator/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc1-load-generator/.settings/org.eclipse.jdt.ui.prefs
index 4d01df75552c562406705858b6368ecf59d6e82f..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc1-load-generator/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc1-load-generator/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,25 +12,72 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
 cleanup.remove_redundant_semicolons=true
@@ -37,6 +85,7 @@ cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,28 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
 org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -80,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -115,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc1-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc1-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/uc1-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/uc1-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/uc1-load-generator/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc1-load-generator/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/uc1-load-generator/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/uc1-load-generator/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc1-load-generator/build.gradle b/theodolite-benchmarks/uc1-load-generator/build.gradle
index aadd4796d86dd46ca6094b00479f9f8483fc7e15..e4791c176c74ddc32b9d72057edfd8c65f291851 100644
--- a/theodolite-benchmarks/uc1-load-generator/build.gradle
+++ b/theodolite-benchmarks/uc1-load-generator/build.gradle
@@ -2,4 +2,4 @@ plugins {
   id 'theodolite.load-generator'
 }
 
-mainClassName = "theodolite.uc1.workloadgenerator.LoadGenerator"
+mainClassName = "rocks.theodolite.benchmarks.uc1.loadgenerator.LoadGenerator"
diff --git a/theodolite-benchmarks/uc1-load-generator/src/main/java/theodolite/uc1/workloadgenerator/LoadGenerator.java b/theodolite-benchmarks/uc1-load-generator/src/main/java/rocks/theodolite/benchmarks/uc1/loadgenerator/LoadGenerator.java
similarity index 78%
rename from theodolite-benchmarks/uc1-load-generator/src/main/java/theodolite/uc1/workloadgenerator/LoadGenerator.java
rename to theodolite-benchmarks/uc1-load-generator/src/main/java/rocks/theodolite/benchmarks/uc1/loadgenerator/LoadGenerator.java
index 26741eb33b2a8d1c23a40938d1261254ac37b636..8817ac90839ab4263c4cde380409ebc89a016de5 100644
--- a/theodolite-benchmarks/uc1-load-generator/src/main/java/theodolite/uc1/workloadgenerator/LoadGenerator.java
+++ b/theodolite-benchmarks/uc1-load-generator/src/main/java/rocks/theodolite/benchmarks/uc1/loadgenerator/LoadGenerator.java
@@ -1,4 +1,4 @@
-package theodolite.uc1.workloadgenerator;
+package rocks.theodolite.benchmarks.uc1.loadgenerator;
 
 import java.io.IOException;
 import org.slf4j.Logger;
@@ -18,6 +18,6 @@ public final class LoadGenerator {
    */
   public static void main(final String[] args) throws InterruptedException, IOException {
     LOGGER.info("Start workload generator for use case UC1.");
-    theodolite.commons.workloadgeneration.LoadGenerator.fromEnvironment().run();
+    rocks.theodolite.benchmarks.loadgenerator.LoadGenerator.fromEnvironment().run();
   }
 }
diff --git a/theodolite-benchmarks/uc2-beam-flink/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc2-beam-flink/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/uc2-beam-flink/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc2-beam-flink/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc2-beam-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc2-beam-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc2-beam-flink/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc2-beam-flink/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc2-beam-flink/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc2-beam-flink/build.gradle b/theodolite-benchmarks/uc2-beam-flink/build.gradle
index 9ab898cd465abe20e855d06ebf85373e46ab12e2..095d166fc2dc17957c263cc36255831afb45887d 100644
--- a/theodolite-benchmarks/uc2-beam-flink/build.gradle
+++ b/theodolite-benchmarks/uc2-beam-flink/build.gradle
@@ -2,9 +2,18 @@ plugins {
   id 'theodolite.beam.flink'
 }
 
-
 dependencies {
   implementation project(':uc2-beam')
 }
 
-mainClassName = "application.Uc2BeamFlink"
+sourceSets {
+  main {
+    resources {
+      srcDirs += [
+        project(':uc2-beam').sourceSets.main.resources
+      ]
+    }
+  }
+}
+
+mainClassName = "rocks.theodolite.benchmarks.uc2.beam.flink.Uc2BeamFlink"
diff --git a/theodolite-benchmarks/uc2-beam-flink/src/main/java/application/Uc2BeamFlink.java b/theodolite-benchmarks/uc2-beam-flink/src/main/java/application/Uc2BeamFlink.java
deleted file mode 100644
index f5bb849e626444929e00b17b1324a08c41cb19a0..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc2-beam-flink/src/main/java/application/Uc2BeamFlink.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package application;
-
-import org.apache.beam.runners.flink.FlinkRunner;
-import org.apache.beam.sdk.Pipeline;
-import theodolite.commons.beam.AbstractBeamService;
-
-/**
- * Implementation of the use case Downsampling using Apache Beam with the Flink Runner. To execute
- * locally in standalone start Kafka, Zookeeper, the schema-registry and the workload generator
- * using the delayed_startup.sh script. Start a Flink cluster and pass its REST adress
- * using--flinkMaster as run parameter.
- */
-public final class Uc2BeamFlink extends AbstractBeamService {
-
-  /**
-   * Private constructor setting specific options for this use case.
-   */
-  private Uc2BeamFlink(final String[] args) { // NOPMD
-    super(args);
-    this.options.setRunner(FlinkRunner.class);
-  }
-
-  /**
-   * Start running this microservice.
-   */
-  public static void main(final String[] args) {
-
-    final Uc2BeamFlink uc2BeamFlink = new Uc2BeamFlink(args);
-
-    final Pipeline pipeline = new Uc2BeamPipeline(uc2BeamFlink.options, uc2BeamFlink.getConfig());
-
-    pipeline.run().waitUntilFinish();
-  }
-}
-
diff --git a/theodolite-benchmarks/uc2-beam-flink/src/main/java/rocks/theodolite/benchmarks/uc2/beam/flink/Uc2BeamFlink.java b/theodolite-benchmarks/uc2-beam-flink/src/main/java/rocks/theodolite/benchmarks/uc2/beam/flink/Uc2BeamFlink.java
new file mode 100644
index 0000000000000000000000000000000000000000..2772d76fa26f504827ab74acb8fccc45f117365c
--- /dev/null
+++ b/theodolite-benchmarks/uc2-beam-flink/src/main/java/rocks/theodolite/benchmarks/uc2/beam/flink/Uc2BeamFlink.java
@@ -0,0 +1,21 @@
+package rocks.theodolite.benchmarks.uc2.beam.flink;
+
+import org.apache.beam.runners.flink.FlinkRunner;
+import rocks.theodolite.benchmarks.commons.beam.BeamService;
+import rocks.theodolite.benchmarks.uc2.beam.PipelineFactory;
+
+/**
+ * Implementation of the use case Downsampling using Apache Beam with the Flink Runner. To execute
+ * locally in standalone start Kafka, Zookeeper, the schema-registry and the workload generator
+ * using the delayed_startup.sh script. Start a Flink cluster and pass its REST adress
+ * using--flinkMaster as run parameter.
+ */
+public final class Uc2BeamFlink {
+
+  private Uc2BeamFlink() {}
+
+  public static void main(final String[] args) {
+    new BeamService(PipelineFactory.factory(), FlinkRunner.class, args).runStandalone();
+  }
+}
+
diff --git a/theodolite-benchmarks/uc2-beam-samza/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc2-beam-samza/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/uc2-beam-samza/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc2-beam-samza/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc2-beam-samza/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc2-beam-samza/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc2-beam-samza/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc2-beam-samza/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc2-beam-samza/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc2-beam-samza/Dockerfile b/theodolite-benchmarks/uc2-beam-samza/Dockerfile
index 22855cea279819cacbf6eee253c30c60409fdba3..ae762791c40fc6981ce7e5fd08bea860ed9208ec 100644
--- a/theodolite-benchmarks/uc2-beam-samza/Dockerfile
+++ b/theodolite-benchmarks/uc2-beam-samza/Dockerfile
@@ -5,4 +5,4 @@ ENV MAX_SOURCE_PARALLELISM=1024
 ADD build/distributions/uc2-beam-samza.tar /
 ADD samza-standalone.properties /
 
-CMD /uc2-beam-samza/bin/uc2-beam-samza --configFactory=org.apache.samza.config.factories.PropertiesConfigFactory --configFilePath=samza-standalone.properties --samzaExecutionEnvironment=STANDALONE --maxSourceParallelism=$MAX_SOURCE_PARALLELISM --enableMetrics=false --configOverride="{\"job.coordinator.zk.connect\":\"$SAMZA_JOB_COORDINATOR_ZK_CONNECT\"}"
+CMD /uc2-beam-samza/bin/uc2-beam-samza --configFilePath=samza-standalone.properties --samzaExecutionEnvironment=STANDALONE --maxSourceParallelism=$MAX_SOURCE_PARALLELISM --enableMetrics=false --configOverride="{\"job.coordinator.zk.connect\":\"$SAMZA_JOB_COORDINATOR_ZK_CONNECT\"}"
diff --git a/theodolite-benchmarks/uc2-beam-samza/build.gradle b/theodolite-benchmarks/uc2-beam-samza/build.gradle
index 29d7f9ac0c22c421072646ca665b3849c558d56f..c8148e3bb59f59fb06638d33c40a21750323f757 100644
--- a/theodolite-benchmarks/uc2-beam-samza/build.gradle
+++ b/theodolite-benchmarks/uc2-beam-samza/build.gradle
@@ -2,9 +2,18 @@ plugins {
   id 'theodolite.beam.samza'
 }
 
-
 dependencies {
   implementation project(':uc2-beam')
 }
 
-mainClassName = "application.Uc2BeamSamza"
+sourceSets {
+  main {
+    resources {
+      srcDirs += [
+        project(':uc2-beam').sourceSets.main.resources
+      ]
+    }
+  }
+}
+
+mainClassName = "rocks.theodolite.benchmarks.uc2.beam.samza.Uc2BeamSamza"
diff --git a/theodolite-benchmarks/uc2-beam-samza/src/main/java/application/Uc2BeamSamza.java b/theodolite-benchmarks/uc2-beam-samza/src/main/java/rocks/theodolite/benchmarks/uc2/beam/samza/Uc2BeamSamza.java
similarity index 56%
rename from theodolite-benchmarks/uc2-beam-samza/src/main/java/application/Uc2BeamSamza.java
rename to theodolite-benchmarks/uc2-beam-samza/src/main/java/rocks/theodolite/benchmarks/uc2/beam/samza/Uc2BeamSamza.java
index d4b3d6d910824a718bffe8dc5f0204d53b9865c1..1b3f4ac8a2d052f0d34051e6b17b62100feb129d 100644
--- a/theodolite-benchmarks/uc2-beam-samza/src/main/java/application/Uc2BeamSamza.java
+++ b/theodolite-benchmarks/uc2-beam-samza/src/main/java/rocks/theodolite/benchmarks/uc2/beam/samza/Uc2BeamSamza.java
@@ -1,8 +1,8 @@
-package application;
+package rocks.theodolite.benchmarks.uc2.beam.samza;
 
 import org.apache.beam.runners.samza.SamzaRunner;
-import org.apache.beam.sdk.Pipeline;
-import theodolite.commons.beam.AbstractBeamService;
+import rocks.theodolite.benchmarks.commons.beam.BeamService;
+import rocks.theodolite.benchmarks.uc2.beam.PipelineFactory;
 
 /**
  * Implementation of the use case Downsampling using Apache Beam with the Samza Runner. To run
@@ -14,26 +14,13 @@ import theodolite.commons.beam.AbstractBeamService;
  * persist logs add ${workspace_loc:/uc3-application-samza/eclipseConsoleLogs.log} as Output File
  * under Standard Input Output in Common in the Run Configuration Start via Eclipse Run.
  */
-public final class Uc2BeamSamza extends AbstractBeamService {
+public final class Uc2BeamSamza {
 
-  /**
-   * Private constructor setting specific options for this use case.
-   */
-  private Uc2BeamSamza(final String[] args) { //NOPMD
-    super(args);
-    this.options.setRunner(SamzaRunner.class);
-  }
+  private Uc2BeamSamza() {}
 
-  /**
-   * Start running this microservice.
-   */
   public static void main(final String[] args) {
-
-    final Uc2BeamSamza uc2BeamSamza = new Uc2BeamSamza(args);
-
-    final Pipeline pipeline = new Uc2BeamPipeline(uc2BeamSamza.options, uc2BeamSamza.getConfig());
-
-    pipeline.run().waitUntilFinish();
+    new BeamService(PipelineFactory.factory(), SamzaRunner.class, args).runStandalone();
   }
+
 }
 
diff --git a/theodolite-benchmarks/uc2-beam-samza/src/main/resources/META-INF/application.properties b/theodolite-benchmarks/uc2-beam-samza/src/main/resources/META-INF/application.properties
deleted file mode 100644
index 1545a0f6630c8ea51d694f4056ca3aa750463f5b..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc2-beam-samza/src/main/resources/META-INF/application.properties
+++ /dev/null
@@ -1,17 +0,0 @@
-application.name=theodolite-uc2-application
-application.version=0.0.1
-
-kafka.bootstrap.servers=localhost:9092
-kafka.input.topic=input
-kafka.output.topic=output
-kafka.window.duration.minutes=1
-
-schema.registry.url=http://localhost:8081
-
-num.threads=1
-commit.interval.ms=1000
-cache.max.bytes.buffering=-1
-
-specific.avro.reader=True
-enable.auto.commit.config=True
-auto.offset.reset.config=earliest
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc2-beam/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc2-beam/.settings/org.eclipse.jdt.ui.prefs
index 43ccd3dbcdf80e49b8920c8fe242b35c3f604281..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc2-beam/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc2-beam/.settings/org.eclipse.jdt.ui.prefs
@@ -105,6 +105,7 @@ cleanup.strictly_equal_or_different=false
 cleanup.stringbuffer_to_stringbuilder=false
 cleanup.stringbuilder=false
 cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
 cleanup.substring=false
 cleanup.switch=false
 cleanup.system_property=false
@@ -144,6 +145,7 @@ org.eclipse.jdt.ui.ignorelowercasenames=true
 org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
 sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
@@ -156,8 +158,8 @@ sp_cleanup.add_missing_override_annotations_interface_methods=true
 sp_cleanup.add_serial_version_id=false
 sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
-sp_cleanup.always_use_this_for_non_static_field_access=false
-sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
 sp_cleanup.array_with_curly=false
 sp_cleanup.arrays_fill=false
 sp_cleanup.bitwise_conditional_expression=false
@@ -165,7 +167,7 @@ sp_cleanup.boolean_literal=false
 sp_cleanup.boolean_value_rather_than_comparison=false
 sp_cleanup.break_loop=false
 sp_cleanup.collection_cloning=false
-sp_cleanup.comparing_on_criteria=false
+sp_cleanup.comparing_on_criteria=true
 sp_cleanup.comparison_statement=false
 sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
@@ -175,7 +177,7 @@ sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
 sp_cleanup.do_while_rather_than_while=false
 sp_cleanup.double_negation=false
-sp_cleanup.else_if=true
+sp_cleanup.else_if=false
 sp_cleanup.embedded_if=false
 sp_cleanup.evaluate_nullable=false
 sp_cleanup.extract_increment=false
@@ -190,7 +192,7 @@ sp_cleanup.invert_equals=false
 sp_cleanup.join=false
 sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
-sp_cleanup.make_parameters_final=false
+sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
@@ -227,8 +229,8 @@ sp_cleanup.redundant_comparator=false
 sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
@@ -251,7 +253,8 @@ sp_cleanup.static_inner_class=false
 sp_cleanup.strictly_equal_or_different=false
 sp_cleanup.stringbuffer_to_stringbuilder=false
 sp_cleanup.stringbuilder=false
-sp_cleanup.stringbuilder_for_local_vars=true
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
 sp_cleanup.substring=false
 sp_cleanup.switch=false
 sp_cleanup.system_property=false
@@ -273,11 +276,11 @@ sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
 sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
-sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
-sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
 sp_cleanup.use_unboxing=false
 sp_cleanup.use_var=false
-sp_cleanup.useless_continue=false
-sp_cleanup.useless_return=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
 sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc2-beam/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc2-beam/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc2-beam/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc2-beam/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc2-beam/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc2-beam/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc2-beam/src/main/java/application/Uc2BeamPipeline.java b/theodolite-benchmarks/uc2-beam/src/main/java/application/Uc2BeamPipeline.java
deleted file mode 100644
index 02eec9868b0bbfbf6fd45206ff0d4092ac09e1ac..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc2-beam/src/main/java/application/Uc2BeamPipeline.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package application;
-
-import com.google.common.math.Stats;
-import com.google.common.math.StatsAccumulator;
-import java.util.Map;
-import org.apache.beam.sdk.coders.AvroCoder;
-import org.apache.beam.sdk.coders.CoderRegistry;
-import org.apache.beam.sdk.coders.KvCoder;
-import org.apache.beam.sdk.coders.SerializableCoder;
-import org.apache.beam.sdk.coders.StringUtf8Coder;
-import org.apache.beam.sdk.options.PipelineOptions;
-import org.apache.beam.sdk.transforms.Combine;
-import org.apache.beam.sdk.transforms.MapElements;
-import org.apache.beam.sdk.transforms.windowing.FixedWindows;
-import org.apache.beam.sdk.transforms.windowing.Window;
-import org.apache.beam.sdk.values.KV;
-import org.apache.commons.configuration2.Configuration;
-import org.apache.kafka.common.serialization.StringSerializer;
-import org.joda.time.Duration;
-import theodolite.commons.beam.AbstractPipeline;
-import theodolite.commons.beam.ConfigurationKeys;
-import theodolite.commons.beam.kafka.KafkaActivePowerTimestampReader;
-import theodolite.commons.beam.kafka.KafkaWriterTransformation;
-import titan.ccp.model.records.ActivePowerRecord;
-
-
-/**
- * Implementation of the use case Downsampling using Apache Beam.
- */
-public final class Uc2BeamPipeline extends AbstractPipeline {
-
-  protected Uc2BeamPipeline(final PipelineOptions options, final Configuration config) {
-    super(options, config);
-    // Additional needed variables
-    final String outputTopic = config.getString(ConfigurationKeys.KAFKA_OUTPUT_TOPIC);
-
-    final Duration duration =
-        Duration.standardMinutes(config.getInt(ConfigurationKeys.KAFKA_WINDOW_DURATION_MINUTES));
-
-    // Build kafka configuration
-    final Map<String, Object> consumerConfig = buildConsumerConfig();
-
-    // Set Coders for Classes that will be distributed
-    final CoderRegistry cr = getCoderRegistry();
-    cr.registerCoderForClass(ActivePowerRecord.class, AvroCoder.of(ActivePowerRecord.SCHEMA$));
-    cr.registerCoderForClass(StatsAggregation.class, SerializableCoder.of(StatsAggregation.class));
-    cr.registerCoderForClass(StatsAccumulator.class, AvroCoder.of(StatsAccumulator.class));
-
-    // Read from Kafka
-    final KafkaActivePowerTimestampReader kafkaActivePowerRecordReader =
-        new KafkaActivePowerTimestampReader(bootstrapServer, inputTopic, consumerConfig);
-
-    // Transform into String
-    final StatsToString statsToString = new StatsToString();
-
-    // Write to Kafka
-    final KafkaWriterTransformation<String> kafkaWriter =
-        new KafkaWriterTransformation<>(bootstrapServer, outputTopic, StringSerializer.class);
-
-    // Apply pipeline transformations
-    this.apply(kafkaActivePowerRecordReader)
-        // Apply a fixed window
-        .apply(Window.<KV<String, ActivePowerRecord>>into(FixedWindows.of(duration)))
-        // Aggregate per window for every key
-        .apply(Combine.<String, ActivePowerRecord, Stats>perKey(new StatsAggregation()))
-        .setCoder(KvCoder.of(StringUtf8Coder.of(), SerializableCoder.of(Stats.class)))
-        // Map into correct output format
-        .apply(MapElements.via(statsToString))
-        // Write to Kafka
-        .apply(kafkaWriter);
-  }
-}
-
diff --git a/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/PipelineFactory.java b/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/PipelineFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..375b2a6cba5256e0644b6beaf26d41e010089250
--- /dev/null
+++ b/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/PipelineFactory.java
@@ -0,0 +1,87 @@
+package rocks.theodolite.benchmarks.uc2.beam;
+
+import com.google.common.math.Stats;
+import com.google.common.math.StatsAccumulator;
+import java.util.function.Function;
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.coders.AvroCoder;
+import org.apache.beam.sdk.coders.CoderRegistry;
+import org.apache.beam.sdk.coders.KvCoder;
+import org.apache.beam.sdk.coders.SerializableCoder;
+import org.apache.beam.sdk.coders.StringUtf8Coder;
+import org.apache.beam.sdk.options.PipelineOptions;
+import org.apache.beam.sdk.transforms.Combine;
+import org.apache.beam.sdk.transforms.MapElements;
+import org.apache.beam.sdk.transforms.windowing.FixedWindows;
+import org.apache.beam.sdk.transforms.windowing.Window;
+import org.apache.beam.sdk.values.KV;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.kafka.common.serialization.StringSerializer;
+import org.joda.time.Duration;
+import rocks.theodolite.benchmarks.commons.beam.AbstractPipelineFactory;
+import rocks.theodolite.benchmarks.commons.beam.ConfigurationKeys;
+import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaActivePowerTimestampReader;
+import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaWriterTransformation;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * {@link AbstractPipelineFactory} for UC2.
+ */
+public class PipelineFactory extends AbstractPipelineFactory {
+
+  public PipelineFactory(final Configuration configuration) {
+    super(configuration);
+  }
+
+  @Override
+  protected void expandOptions(final PipelineOptions options) {
+    // No options to set
+  }
+
+  @Override
+  protected void constructPipeline(final Pipeline pipeline) {
+    final String outputTopic = this.config.getString(ConfigurationKeys.KAFKA_OUTPUT_TOPIC);
+
+    final Duration duration = Duration.standardMinutes(
+        this.config.getInt(ConfigurationKeys.KAFKA_WINDOW_DURATION_MINUTES));
+
+    final KafkaActivePowerTimestampReader kafkaReader = super.buildKafkaReader();
+
+    // Transform into String
+    final StatsToString statsToString = new StatsToString();
+
+    // Write to Kafka
+    final String bootstrapServer = this.config.getString(ConfigurationKeys.KAFKA_BOOTSTRAP_SERVERS);
+    final KafkaWriterTransformation<String> kafkaWriter =
+        new KafkaWriterTransformation<>(bootstrapServer, outputTopic, StringSerializer.class);
+
+    // Apply pipeline transformations
+    pipeline.apply(kafkaReader)
+        // Apply a fixed window
+        .apply(Window.<KV<String, ActivePowerRecord>>into(FixedWindows.of(duration)))
+        // Aggregate per window for every key
+        .apply(Combine.<String, ActivePowerRecord, Stats>perKey(new StatsAggregation()))
+        .setCoder(KvCoder.of(StringUtf8Coder.of(), SerializableCoder.of(Stats.class)))
+        // Map into correct output format
+        .apply(MapElements.via(statsToString))
+        // Write to Kafka
+        .apply(kafkaWriter);
+  }
+
+  @Override
+  protected void registerCoders(final CoderRegistry registry) {
+    registry.registerCoderForClass(
+        ActivePowerRecord.class,
+        // AvroCoder.of(ActivePowerRecord.SCHEMA$));
+        AvroCoder.of(ActivePowerRecord.class, false));
+    registry.registerCoderForClass(StatsAggregation.class,
+        SerializableCoder.of(StatsAggregation.class));
+    registry.registerCoderForClass(StatsAccumulator.class,
+        AvroCoder.of(StatsAccumulator.class));
+  }
+
+  public static Function<Configuration, AbstractPipelineFactory> factory() {
+    return config -> new PipelineFactory(config);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc2-beam/src/main/java/application/StatsAggregation.java b/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/StatsAggregation.java
similarity index 96%
rename from theodolite-benchmarks/uc2-beam/src/main/java/application/StatsAggregation.java
rename to theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/StatsAggregation.java
index 688f6677ec6d74e063a07a20c079b783aa71c399..a8956ee4b55c1e545e2c25ce38e2911b7c961337 100644
--- a/theodolite-benchmarks/uc2-beam/src/main/java/application/StatsAggregation.java
+++ b/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/StatsAggregation.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc2.beam;
 
 import com.google.common.math.Stats;
 import com.google.common.math.StatsAccumulator;
diff --git a/theodolite-benchmarks/uc2-beam/src/main/java/application/StatsToString.java b/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/StatsToString.java
similarity index 91%
rename from theodolite-benchmarks/uc2-beam/src/main/java/application/StatsToString.java
rename to theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/StatsToString.java
index 9a73ae8e1681b2c350dee328cba7283cf3386fd7..222c9f3a1be0604f42c0d5d70308253463bb66f5 100644
--- a/theodolite-benchmarks/uc2-beam/src/main/java/application/StatsToString.java
+++ b/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/StatsToString.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc2.beam;
 
 import com.google.common.math.Stats;
 import org.apache.beam.sdk.transforms.SimpleFunction;
diff --git a/theodolite-benchmarks/uc2-beam-flink/src/main/resources/META-INF/application.properties b/theodolite-benchmarks/uc2-beam/src/main/resources/META-INF/application.properties
similarity index 75%
rename from theodolite-benchmarks/uc2-beam-flink/src/main/resources/META-INF/application.properties
rename to theodolite-benchmarks/uc2-beam/src/main/resources/META-INF/application.properties
index 1545a0f6630c8ea51d694f4056ca3aa750463f5b..c6672125a8b6a074cb7eca31bd90700cd4da736a 100644
--- a/theodolite-benchmarks/uc2-beam-flink/src/main/resources/META-INF/application.properties
+++ b/theodolite-benchmarks/uc2-beam/src/main/resources/META-INF/application.properties
@@ -12,6 +12,7 @@ num.threads=1
 commit.interval.ms=1000
 cache.max.bytes.buffering=-1
 
-specific.avro.reader=True
-enable.auto.commit.config=True
-auto.offset.reset.config=earliest
\ No newline at end of file
+specific.avro.reader=true
+enable.auto.commit=true
+max.poll.records=500
+auto.offset.reset=earliest
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc2-flink/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc2-flink/.settings/org.eclipse.jdt.ui.prefs
index 4d01df75552c562406705858b6368ecf59d6e82f..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc2-flink/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc2-flink/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,25 +12,72 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
 cleanup.remove_redundant_semicolons=true
@@ -37,6 +85,7 @@ cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,28 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
 org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -80,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -115,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc2-flink/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc2-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/uc2-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/uc2-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/uc2-flink/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc2-flink/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/uc2-flink/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/uc2-flink/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc2-flink/Dockerfile b/theodolite-benchmarks/uc2-flink/Dockerfile
index 537ab28e2d4e5fb8edfc2760142acc33cc49b91d..01a85c57b00ea8bb4af8faa697708fd2b650de50 100644
--- a/theodolite-benchmarks/uc2-flink/Dockerfile
+++ b/theodolite-benchmarks/uc2-flink/Dockerfile
@@ -1,3 +1,3 @@
-FROM flink:1.12-scala_2.12-java11
+FROM flink:1.13-java11
 
 ADD build/libs/uc2-flink-all.jar /opt/flink/usrlib/artifacts/uc2-flink-all.jar
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc2-flink/build.gradle b/theodolite-benchmarks/uc2-flink/build.gradle
index 0be6f3773f508dc84cad6a62b125b6a889edb383..ea4d2d8b285792b8ce66484d0d9c0907a7c49957 100644
--- a/theodolite-benchmarks/uc2-flink/build.gradle
+++ b/theodolite-benchmarks/uc2-flink/build.gradle
@@ -2,4 +2,4 @@ plugins {
   id 'theodolite.flink'
 }
 
-mainClassName = "theodolite.uc2.application.HistoryServiceFlinkJob"
+mainClassName = "rocks.theodolite.benchmarks.uc2.flink.HistoryServiceFlinkJob"
diff --git a/theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/ConfigurationKeys.java b/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/ConfigurationKeys.java
similarity index 96%
rename from theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/ConfigurationKeys.java
rename to theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/ConfigurationKeys.java
index e8261062689ce4c586a4e6fbde02878a28f48e97..bcb15b7d655d9a05b0b65d4dda480379173a8212 100644
--- a/theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/ConfigurationKeys.java
+++ b/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/ConfigurationKeys.java
@@ -1,4 +1,4 @@
-package theodolite.uc2.application;
+package rocks.theodolite.benchmarks.uc2.flink;
 
 /**
  * Keys to access configuration parameters.
diff --git a/theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/HistoryServiceFlinkJob.java b/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/HistoryServiceFlinkJob.java
similarity index 93%
rename from theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/HistoryServiceFlinkJob.java
rename to theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/HistoryServiceFlinkJob.java
index d156d895d86bb01a31f96e08764df8b8df743c4d..7e67be897ce06f9f12e3fbcefb61d44a0775eea5 100644
--- a/theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/HistoryServiceFlinkJob.java
+++ b/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/HistoryServiceFlinkJob.java
@@ -1,11 +1,10 @@
-package theodolite.uc2.application;
+package rocks.theodolite.benchmarks.uc2.flink;
 
 import com.google.common.math.Stats;
 import org.apache.commons.configuration2.Configuration;
 import org.apache.flink.api.common.typeinfo.Types;
 import org.apache.flink.api.java.tuple.Tuple2;
 import org.apache.flink.runtime.state.StateBackend;
-import org.apache.flink.streaming.api.TimeCharacteristic;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
 import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows;
 import org.apache.flink.streaming.api.windowing.time.Time;
@@ -14,9 +13,9 @@ import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer;
 import org.apache.kafka.common.serialization.Serdes;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import theodolite.commons.flink.KafkaConnectorFactory;
-import theodolite.commons.flink.StateBackends;
-import theodolite.commons.flink.serialization.StatsSerializer;
+import rocks.theodolite.benchmarks.commons.flink.KafkaConnectorFactory;
+import rocks.theodolite.benchmarks.commons.flink.StateBackends;
+import rocks.theodolite.benchmarks.commons.flink.serialization.StatsSerializer;
 import titan.ccp.common.configuration.ServiceConfigurations;
 import titan.ccp.model.records.ActivePowerRecord;
 
@@ -48,8 +47,6 @@ public final class HistoryServiceFlinkJob {
   }
 
   private void configureEnv() {
-    this.env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
-
     final boolean checkpointing = this.config.getBoolean(ConfigurationKeys.CHECKPOINTING, true);
     final int commitIntervalMs = this.config.getInt(ConfigurationKeys.COMMIT_INTERVAL_MS);
     if (checkpointing) {
diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/StatsAggregateFunction.java b/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/StatsAggregateFunction.java
similarity index 90%
rename from theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/StatsAggregateFunction.java
rename to theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/StatsAggregateFunction.java
index 4706da0a9491e0391f25cd61639c3bb565509cb1..b2a9e5f538c9e92ba777dbcd61caaa3199ebb383 100644
--- a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/StatsAggregateFunction.java
+++ b/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/StatsAggregateFunction.java
@@ -1,9 +1,9 @@
-package theodolite.uc3.application;
+package rocks.theodolite.benchmarks.uc2.flink;
 
 import com.google.common.math.Stats;
 import com.google.common.math.StatsAccumulator;
 import org.apache.flink.api.common.functions.AggregateFunction;
-import theodolite.uc3.application.util.StatsFactory;
+import rocks.theodolite.benchmarks.uc2.flink.util.StatsFactory;
 import titan.ccp.model.records.ActivePowerRecord;
 
 /**
diff --git a/theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/StatsProcessWindowFunction.java b/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/StatsProcessWindowFunction.java
similarity index 94%
rename from theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/StatsProcessWindowFunction.java
rename to theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/StatsProcessWindowFunction.java
index d422c37b667d9d3309f0dd858758db29051807b9..a8451a41a1445b88102ab25fee1d92b73bd33e22 100644
--- a/theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/StatsProcessWindowFunction.java
+++ b/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/StatsProcessWindowFunction.java
@@ -1,4 +1,4 @@
-package theodolite.uc2.application;
+package rocks.theodolite.benchmarks.uc2.flink;
 
 import com.google.common.math.Stats;
 import org.apache.flink.api.java.tuple.Tuple2;
diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/StatsFactory.java b/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/util/StatsFactory.java
similarity index 91%
rename from theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/StatsFactory.java
rename to theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/util/StatsFactory.java
index b7880be4eb48035959251cc56273d16407bcb888..9fbddcc6d1a0ca6a01d9bc20f8acec7f01ec155a 100644
--- a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/StatsFactory.java
+++ b/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/util/StatsFactory.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.application.util;
+package rocks.theodolite.benchmarks.uc2.flink.util;
 
 import com.google.common.math.Stats;
 import com.google.common.math.StatsAccumulator;
diff --git a/theodolite-benchmarks/uc2-hazelcastjet/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc2-hazelcastjet/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/uc2-hazelcastjet/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc2-hazelcastjet/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc2-hazelcastjet/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc2-hazelcastjet/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc2-hazelcastjet/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc2-hazelcastjet/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc2-hazelcastjet/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc2-hazelcastjet/Dockerfile b/theodolite-benchmarks/uc2-hazelcastjet/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..4a7680e29042025d48c4c37a8f424871fe48bbf8
--- /dev/null
+++ b/theodolite-benchmarks/uc2-hazelcastjet/Dockerfile
@@ -0,0 +1,7 @@
+FROM openjdk:11-slim
+
+ADD build/distributions/uc2-hazelcastjet.tar /
+
+
+CMD  JAVA_OPTS="$JAVA_OPTS -Dorg.slf4j.simpleLogger.defaultLogLevel=$LOG_LEVEL" \
+     /uc2-hazelcastjet/bin/uc2-hazelcastjet
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc2-hazelcastjet/build.gradle b/theodolite-benchmarks/uc2-hazelcastjet/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..ef1597413570a5d7b3af8538ced8d4a98d4fa6f8
--- /dev/null
+++ b/theodolite-benchmarks/uc2-hazelcastjet/build.gradle
@@ -0,0 +1,5 @@
+plugins {
+  id 'theodolite.hazelcastjet'
+}
+
+mainClassName = "rocks.theodolite.benchmarks.uc2.hazelcastjet.HistoryService"
diff --git a/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/HistoryService.java b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/HistoryService.java
new file mode 100644
index 0000000000000000000000000000000000000000..f382978b714fdfdff6c190339c2ed23a2e037069
--- /dev/null
+++ b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/HistoryService.java
@@ -0,0 +1,70 @@
+package rocks.theodolite.benchmarks.uc2.hazelcastjet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A microservice that manages the history and, therefore, stores and aggregates incoming
+ * measurements.
+ */
+public class HistoryService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(HistoryService.class);
+
+  // Hazelcast settings (default)
+  private static final String HZ_KUBERNETES_SERVICE_DNS_KEY = "service-dns";
+  private static final String BOOTSTRAP_SERVER_DEFAULT = "localhost:5701";
+
+  // Kafka settings (default)
+  private static final String KAFKA_BOOTSTRAP_DEFAULT = "localhost:9092";
+  private static final String SCHEMA_REGISTRY_URL_DEFAULT = "http://localhost:8081";
+  private static final String KAFKA_INPUT_TOPIC_DEFAULT = "input";
+  private static final String KAFKA_OUTPUT_TOPIC_DEFAULT = "output";
+
+  // UC2 specific (default)
+  private static final String DOWNSAMPLE_INTERVAL_DEFAULT_MS = "60000";
+
+  // Job name (default)
+  private static final String JOB_NAME = "uc2-hazelcastjet";
+
+  /**
+   * Entrypoint for UC2 using Gradle Run.
+   */
+  public static void main(final String[] args) {
+    final HistoryService uc2HistoryService = new HistoryService();
+    try {
+      uc2HistoryService.run();
+    } catch (final Exception e) { // NOPMD
+      LOGGER.error("ABORT MISSION!: {}", e);
+    }
+  }
+
+  /**
+   * Start a UC2 service.
+   *
+   * @throws Exception This Exception occurs if the Uc2HazelcastJetFactory is used in the wrong way.
+   *         Detailed data is provided once an Exception occurs.
+   */
+  public void run() throws Exception { // NOPMD
+    this.createHazelcastJetApplication();
+  }
+
+  /**
+   * Creates a Hazelcast Jet Application for UC2 using the Uc1HazelcastJetFactory.
+   *
+   * @throws Exception This Exception occurs if the Uc2HazelcastJetFactory is used in the wrong way.
+   *         Detailed data is provided once an Exception occurs.
+   */
+  private void createHazelcastJetApplication() throws Exception { // NOPMD
+    new Uc2HazelcastJetFactory()
+        .setReadPropertiesFromEnv(KAFKA_BOOTSTRAP_DEFAULT, SCHEMA_REGISTRY_URL_DEFAULT,JOB_NAME)
+        .setWritePropertiesFromEnv(KAFKA_BOOTSTRAP_DEFAULT,SCHEMA_REGISTRY_URL_DEFAULT)
+        .setKafkaInputTopicFromEnv(KAFKA_INPUT_TOPIC_DEFAULT)
+        .setKafkaOutputTopicFromEnv(KAFKA_OUTPUT_TOPIC_DEFAULT)
+        .setDownsampleIntervalFromEnv(DOWNSAMPLE_INTERVAL_DEFAULT_MS)
+        .buildUc2Pipeline()
+        .buildUc2JetInstanceFromEnv(LOGGER, BOOTSTRAP_SERVER_DEFAULT, HZ_KUBERNETES_SERVICE_DNS_KEY)
+        .runUc2Job(JOB_NAME);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2HazelcastJetFactory.java b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2HazelcastJetFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..143b154f3726e75d2842766b49bd2e26f57ce39b
--- /dev/null
+++ b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2HazelcastJetFactory.java
@@ -0,0 +1,301 @@
+package rocks.theodolite.benchmarks.uc2.hazelcastjet;
+
+import com.google.common.math.StatsAccumulator;
+import com.hazelcast.jet.JetInstance;
+import com.hazelcast.jet.config.JobConfig;
+import com.hazelcast.jet.pipeline.Pipeline;
+import io.confluent.kafka.serializers.KafkaAvroDeserializer;
+import java.util.Objects;
+import java.util.Properties;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import org.apache.kafka.common.serialization.StringSerializer;
+import org.slf4j.Logger;
+import rocks.theodolite.benchmarks.commons.hazelcastjet.ConfigurationKeys;
+import rocks.theodolite.benchmarks.commons.hazelcastjet.JetInstanceBuilder;
+import rocks.theodolite.benchmarks.commons.hazelcastjet.KafkaPropertiesBuilder;
+import rocks.theodolite.benchmarks.uc2.hazelcastjet.uc2specifics.StatsAccumulatorSerializer;
+
+/**
+ * A Hazelcast Jet factory which can build a Hazelcast Jet Instance and Pipeline for the UC2
+ * benchmark and lets you start the Hazelcast Jet job. The JetInstance can be built directly as the
+ * Hazelcast Config is managed internally. In order to build the Pipeline, you first have to build
+ * the Read and Write Properties, set the input and output topic, and set the downsample interval
+ * which can be done using internal functions of this factory. Outside data only refers to custom
+ * values or default values in case data of the environment cannot the fetched.
+ */
+public class Uc2HazelcastJetFactory {
+
+  // Information per History Service
+  private Properties kafkaReadPropsForPipeline;
+  private Properties kafkaWritePropsForPipeline;
+  private String kafkaInputTopic;
+  private String kafkaOutputTopic;
+  private JetInstance uc2JetInstance;
+  private Pipeline uc2JetPipeline;
+  // UC2 specific
+  private int downsampleInterval;
+
+  /////////////////////////////////////
+  // Layer 1 - Hazelcast Jet Run Job //
+  /////////////////////////////////////
+
+  /**
+   * Needs a JetInstance and Pipeline defined in this factors. Adds the pipeline to the existing
+   * JetInstance as a job.
+   *
+   * @param jobName The name of the job.
+   */
+  public void runUc2Job(final String jobName) {
+
+    // Check if a Jet Instance for UC2 is set.
+    if (this.uc2JetInstance == null) {
+      throw new IllegalStateException("Jet Instance is not set! "
+          + "Cannot start a hazelcast jet job for UC2.");
+    }
+
+    // Check if a Pipeline for UC2 is set.
+    if (this.uc2JetPipeline == null) {
+      throw new IllegalStateException(
+          "Hazelcast Pipeline is not set! Cannot start a hazelcast jet job for UC2.");
+    }
+
+    // Adds the job name and joins a job to the JetInstance defined in this factory
+    final JobConfig jobConfig = new JobConfig();
+    jobConfig.registerSerializer(StatsAccumulator.class, StatsAccumulatorSerializer.class);
+    jobConfig.setName(jobName);
+    this.uc2JetInstance.newJobIfAbsent(this.uc2JetPipeline, jobConfig).join();
+  }
+
+  /////////////
+  // Layer 2 //
+  /////////////
+
+  /**
+   * Build a Hazelcast JetInstance used to run a job on.
+   *
+   * @param logger The logger specified for this JetInstance.
+   * @param bootstrapServerDefault Default bootstrap server in case no value can be derived from the
+   *        environment.
+   * @param hzKubernetesServiceDnsKey The kubernetes service dns key.
+   * @return A Uc2HazelcastJetFactory containing a set JetInstance.
+   */
+  public Uc2HazelcastJetFactory buildUc2JetInstanceFromEnv(final Logger logger,
+      final String bootstrapServerDefault,
+      final String hzKubernetesServiceDnsKey) {
+    this.uc2JetInstance = new JetInstanceBuilder()
+        .setConfigFromEnv(logger, bootstrapServerDefault, hzKubernetesServiceDnsKey)
+        .build();
+    return this;
+  }
+
+  /**
+   * Builds a Hazelcast Jet pipeline used for a JetInstance to run it as a job on. Needs the input
+   * topic and kafka properties defined in this factory beforehand.
+   *
+   * @return A Uc2HazelcastJetFactory containg a set pipeline.
+   * @throws Exception If the input topic or the kafka properties are not defined, the pipeline
+   *         cannot be built.
+   */
+  public Uc2HazelcastJetFactory buildUc2Pipeline() throws IllegalStateException { // NOPMD
+
+    final String defaultPipelineWarning = "Cannot build pipeline."; // NOPMD
+
+    // Check if Properties for the Kafka Input are set.
+    if (this.kafkaReadPropsForPipeline == null) {
+      throw new IllegalStateException("Kafka Read Properties for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if Properties for the Kafka Output are set.
+    if (this.kafkaWritePropsForPipeline == null) {
+      throw new IllegalStateException("Kafka Write Properties for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if the Kafka input topic is set.
+    if (this.kafkaInputTopic == null) {
+      throw new IllegalStateException("Kafka input topic for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if the Kafka output topic is set.
+    if (this.kafkaOutputTopic == null) {
+      throw new IllegalStateException("kafka output topic for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if the downsampleInterval (tumbling window time) is set.
+    if (this.downsampleInterval <= 0) {
+      throw new IllegalStateException(
+          "downsample interval for pipeline not set or not bigger than 0! "
+              + defaultPipelineWarning);
+    }
+
+    // Build Pipeline Using the pipelineBuilder
+    final Uc2PipelineBuilder pipeBuilder = new Uc2PipelineBuilder();
+    this.uc2JetPipeline =
+        pipeBuilder.build(this.kafkaReadPropsForPipeline, this.kafkaWritePropsForPipeline,
+            this.kafkaInputTopic, this.kafkaOutputTopic, this.downsampleInterval);
+    // Return Uc2HazelcastJetBuilder factory
+    return this;
+  }
+
+  /////////////
+  // Layer 3 //
+  /////////////
+
+  /**
+   * Sets kafka read properties for pipeline used in this builder.
+   *
+   * @param kafkaReadProperties A propeties object containing necessary values used for the hazelcst
+   *        jet kafka connection to read data.
+   * @return The Uc2HazelcastJetBuilder factory with set kafkaReadPropsForPipeline.
+   */
+  public Uc2HazelcastJetFactory setCustomReadProperties(// NOPMD
+      final Properties kafkaReadProperties) {
+    this.kafkaReadPropsForPipeline = kafkaReadProperties;
+    return this;
+  }
+
+  /**
+   * Sets kafka write properties for pipeline used in this builder.
+   *
+   * @param kafkaWriteProperties A propeties object containing necessary values used for the
+   *        hazelcst jet kafka connection to write data.
+   * @return The Uc2HazelcastJetBuilder factory with set kafkaWritePropsForPipeline.
+   */
+  public Uc2HazelcastJetFactory setCustomWriteProperties(// NOPMD
+      final Properties kafkaWriteProperties) {
+    this.kafkaWritePropsForPipeline = kafkaWriteProperties;
+    return this;
+  }
+
+  /**
+   * Sets kafka read properties for pipeline used in this builder using environment variables.
+   *
+   * @param bootstrapServersDefault Default Bootstrap server in the case that no bootstrap server
+   *        can be fetched from the environment.
+   * @param schemaRegistryUrlDefault Default schema registry url in the case that no schema registry
+   *        url can be fetched from the environment.
+   * @return The Uc2HazelcastJetBuilder factory with set kafkaReadPropertiesForPipeline.
+   */
+  public Uc2HazelcastJetFactory setReadPropertiesFromEnv(// NOPMD
+                                                         final String bootstrapServersDefault,
+                                                         final String schemaRegistryUrlDefault,
+                                                         final String jobName) {
+    // Use KafkaPropertiesBuilder to build a properties object used for kafka
+    final KafkaPropertiesBuilder propsBuilder = new KafkaPropertiesBuilder();
+    final Properties kafkaReadProps =
+        propsBuilder.buildKafkaInputReadPropsFromEnv(bootstrapServersDefault,
+            schemaRegistryUrlDefault,
+            jobName,
+            StringDeserializer.class.getCanonicalName(),
+            KafkaAvroDeserializer.class.getCanonicalName());
+    this.kafkaReadPropsForPipeline = kafkaReadProps;
+    return this;
+  }
+
+  /**
+   * Sets kafka write properties for pipeline used in this builder using environment variables.
+   *
+   * @param bootstrapServersDefault Default Bootstrap server in the case that no bootstrap server
+   *        can be fetched from the environment.
+   * @return The Uc2HazelcastJetBuilder factory with set kafkaWritePropertiesForPipeline.
+   */
+  public Uc2HazelcastJetFactory setWritePropertiesFromEnv(// NOPMD
+      final String bootstrapServersDefault, final String schemaRegistryUrlDefault) {
+    // Use KafkaPropertiesBuilder to build a properties object used for kafka
+    final KafkaPropertiesBuilder propsBuilder = new KafkaPropertiesBuilder();
+    final Properties kafkaWriteProps =
+        propsBuilder.buildKafkaWritePropsFromEnv(bootstrapServersDefault,
+            schemaRegistryUrlDefault,
+            StringSerializer.class.getCanonicalName(),
+            StringSerializer.class.getCanonicalName());
+    this.kafkaWritePropsForPipeline = kafkaWriteProps;
+    return this;
+  }
+
+  /**
+   * Sets the kafka input topic for the pipeline used in this builder.
+   *
+   * @param inputTopic The kafka topic used as the pipeline input.
+   * @return A Uc2HazelcastJetBuilder factory with a set kafkaInputTopic.
+   */
+  public Uc2HazelcastJetFactory setCustomKafkaInputTopic(// NOPMD
+      final String inputTopic) {
+    this.kafkaInputTopic = inputTopic;
+    return this;
+  }
+
+  /**
+   * Sets the kafka input output for the pipeline used in this builder.
+   *
+   * @param outputTopic The kafka topic used as the pipeline output.
+   * @return A Uc2HazelcastJetBuilder factory with a set kafkaOutputTopic.
+   */
+  public Uc2HazelcastJetFactory setCustomKafkaOutputTopic(final String outputTopic) { // NOPMD
+    this.kafkaOutputTopic = outputTopic;
+    return this;
+  }
+
+
+  /**
+   * Sets the kafka input topic for the pipeline used in this builder using environment variables.
+   *
+   * @param defaultInputTopic The default kafka input topic used if no topic is specified by the
+   *        environment.
+   * @return A Uc2HazelcastJetBuilder factory with a set kafkaInputTopic.
+   */
+  public Uc2HazelcastJetFactory setKafkaInputTopicFromEnv(// NOPMD
+      final String defaultInputTopic) {
+    this.kafkaInputTopic = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_INPUT_TOPIC),
+        defaultInputTopic);
+    return this;
+  }
+
+  /**
+   * Sets the kafka output topic for the pipeline used in this builder using environment variables.
+   *
+   * @param defaultOutputTopic The default kafka output topic used if no topic is specified by the
+   *        environment.
+   * @return A Uc2HazelcastJetBuilder factory with a set kafkaOutputTopic.
+   */
+  public Uc2HazelcastJetFactory setKafkaOutputTopicFromEnv(// NOPMD
+      final String defaultOutputTopic) {
+    this.kafkaOutputTopic = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_OUTPUT_TOPIC),
+        defaultOutputTopic);
+    return this;
+  }
+
+  /**
+   * Sets the downsample interval for the pipeline used in this builder.
+   *
+   * @param downsampleInterval the downsample interval to be used for this pipeline.
+   * @return A Uc2HazelcastJetFactory with a set downsampleInterval.
+   */
+  public Uc2HazelcastJetFactory setCustomDownsampleInterval(// NOPMD
+      final int downsampleInterval) {
+    this.downsampleInterval = downsampleInterval;
+    return this;
+  }
+
+  /**
+   * Sets the downsample interval for the pipeline used in this builder from the environment.
+   *
+   * @param defaultDownsampleInterval the default downsample interval to be used for this pipeline
+   *        when none is set in the environment.
+   * @return A Uc2HazelcastJetFactory with a set downsampleInterval.
+   */
+  public Uc2HazelcastJetFactory setDownsampleIntervalFromEnv(// NOPMD
+      final String defaultDownsampleInterval) {
+    final String downsampleInterval = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.DOWNSAMPLE_INTERVAL),
+        defaultDownsampleInterval);
+    final int downsampleIntervalNumber = Integer.parseInt(downsampleInterval);
+    this.downsampleInterval = downsampleIntervalNumber;
+    return this;
+  }
+
+}
diff --git a/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2PipelineBuilder.java b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2PipelineBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..73377de6122d4a723c5dbbcb8198fa814c4bed1e
--- /dev/null
+++ b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2PipelineBuilder.java
@@ -0,0 +1,135 @@
+package rocks.theodolite.benchmarks.uc2.hazelcastjet;
+
+import com.google.common.math.Stats;
+import com.google.common.math.StatsAccumulator;
+import com.hazelcast.jet.aggregate.AggregateOperation;
+import com.hazelcast.jet.aggregate.AggregateOperation1;
+import com.hazelcast.jet.kafka.KafkaSinks;
+import com.hazelcast.jet.kafka.KafkaSources;
+import com.hazelcast.jet.pipeline.Pipeline;
+import com.hazelcast.jet.pipeline.Sinks;
+import com.hazelcast.jet.pipeline.StreamSource;
+import com.hazelcast.jet.pipeline.StreamStage;
+import com.hazelcast.jet.pipeline.WindowDefinition;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import rocks.theodolite.benchmarks.uc2.hazelcastjet.uc2specifics.StatsAccumulatorSupplier;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * Builder to build a HazelcastJet Pipeline for UC2 which can be used for stream processing using
+ * Hazelcast Jet.
+ */
+public class Uc2PipelineBuilder {
+
+  /**
+   * Builds a pipeline which can be used for stream processing using Hazelcast Jet.
+   *
+   * @param kafkaReadPropsForPipeline Properties Object containing the necessary kafka reads
+   *        attributes.
+   * @param kafkaWritePropsForPipeline Properties Object containing the necessary kafka write
+   *        attributes.
+   * @param kafkaInputTopic The name of the input topic used for the pipeline.
+   * @param kafkaOutputTopic The name of the output topic used for the pipeline.
+   * @param downsampleIntervalInMs The window length of the tumbling window used in the aggregation
+   *        of this pipeline.
+   * @return returns a Pipeline used which can be used in a Hazelcast Jet Instance to process data
+   *         for UC2.
+   */
+  public Pipeline build(final Properties kafkaReadPropsForPipeline,
+      final Properties kafkaWritePropsForPipeline, final String kafkaInputTopic,
+      final String kafkaOutputTopic,
+      final int downsampleIntervalInMs) {
+
+    // Define a new pipeline
+    final Pipeline pipe = Pipeline.create();
+
+    // Define the Kafka Source
+    final StreamSource<Entry<String, ActivePowerRecord>> kafkaSource =
+        KafkaSources.<String, ActivePowerRecord>kafka(kafkaReadPropsForPipeline, kafkaInputTopic);
+
+    // Extend UC2 topology to the pipeline
+    final StreamStage<Map.Entry<String, String>> uc2TopologyProduct =
+        this.extendUc2Topology(pipe, kafkaSource, downsampleIntervalInMs);
+
+    // Add Sink1: Logger
+    uc2TopologyProduct.writeTo(Sinks.logger());
+    // Add Sink2: Write back to kafka for the final benchmark
+    uc2TopologyProduct.writeTo(KafkaSinks.<String, String>kafka(
+        kafkaWritePropsForPipeline, kafkaOutputTopic));
+
+    return pipe;
+  }
+
+  /**
+   * Extends to a blank Hazelcast Jet Pipeline the UC2 topology defined by theodolite.
+   *
+   * <p>
+   * UC2 takes {@code ActivePowerRecord} objects, groups them by keys, windows them in a tumbling
+   * window and aggregates them into {@code Stats} objects. The final map returns an
+   * {@code Entry<String,String>} where the key is the key of the group and the String is the
+   * {@code .toString()} representation of the {@code Stats} object.
+   * </p>
+   *
+   * @param pipe The blank hazelcast jet pipeline to extend the logic to.
+   * @param source A streaming source to fetch data from.
+   * @param downsampleIntervalInMs The size of the tumbling window.
+   * @return A {@code StreamStage<Map.Entry<String,String>>} with the above definition of the key
+   *         and value of the Entry object. It can be used to be further modified or directly be
+   *         written into a sink.
+   */
+  public StreamStage<Map.Entry<String, String>> extendUc2Topology(final Pipeline pipe,
+      final StreamSource<Entry<String, ActivePowerRecord>> source,
+      final int downsampleIntervalInMs) {
+    // Build the pipeline topology.
+    return pipe.readFrom(source)
+        .withNativeTimestamps(0)
+        .setLocalParallelism(1)
+        .groupingKey(record -> record.getValue().getIdentifier())
+        .window(WindowDefinition.tumbling(downsampleIntervalInMs))
+        .aggregate(this.uc2AggregateOperation())
+        .map(agg -> {
+          final String theKey = agg.key();
+          final String theValue = agg.getValue().toString();
+          return Map.entry(theKey, theValue);
+        });
+  }
+
+  /**
+   * Defines an AggregateOperation1 for Hazelcast Jet which is used in the Pipeline of the Hazelcast
+   * Jet implementation of UC2.
+   *
+   * <p>
+   * Takes a windowed and keyed {@code Entry<String,ActivePowerRecord>} elements and returns a
+   * {@Stats} object.
+   * </p>
+   *
+   * @return An AggregateOperation used by Hazelcast Jet in a streaming stage which aggregates
+   *         ActivePowerRecord Objects into Stats Objects.
+   */
+  public AggregateOperation1<Entry<String, ActivePowerRecord>,
+      StatsAccumulator, Stats> uc2AggregateOperation() {
+    // Aggregate Operation to Create a Stats Object from Entry<String,ActivePowerRecord> items using
+    // the Statsaccumulator.
+    return AggregateOperation
+        // Creates the accumulator
+        .withCreate(new StatsAccumulatorSupplier())
+        // Defines the accumulation
+        .<Entry<String, ActivePowerRecord>>andAccumulate((accumulator, item) -> {
+          accumulator.add(item.getValue().getValueInW());
+        })
+        // Defines the combination of spread out instances
+        .andCombine((left, right) -> {
+          final Stats rightStats = right.snapshot();
+          left.addAll(rightStats);
+
+        })
+        // Finishes the aggregation
+        .andExportFinish(
+            (accumulator) -> {
+              return accumulator.snapshot();
+          });
+  }
+
+}
diff --git a/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/uc2specifics/StatsAccumulatorSerializer.java b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/uc2specifics/StatsAccumulatorSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c22b8dd6cc1a7af995a98b4388f40a1a3867ba5
--- /dev/null
+++ b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/uc2specifics/StatsAccumulatorSerializer.java
@@ -0,0 +1,38 @@
+package rocks.theodolite.benchmarks.uc2.hazelcastjet.uc2specifics;
+
+import com.google.common.math.Stats;
+import com.google.common.math.StatsAccumulator;
+import com.hazelcast.nio.ObjectDataInput;
+import com.hazelcast.nio.ObjectDataOutput;
+import com.hazelcast.nio.serialization.StreamSerializer;
+import java.io.IOException;
+
+/**
+ * A serializer and deserializer for the StatsAccumulator which is used in the UC2 implementation
+ * using Hazelcast Jet.
+ */
+public class StatsAccumulatorSerializer implements StreamSerializer<StatsAccumulator> {
+
+  private static final int TYPE_ID = 69_420;
+
+  @Override
+  public int getTypeId() {
+    return TYPE_ID;
+  }
+
+  @Override
+  public void write(final ObjectDataOutput out, final StatsAccumulator object) throws IOException {
+    final byte[] byteArray = object.snapshot().toByteArray();
+    out.writeByteArray(byteArray);
+  }
+
+  @Override
+  public StatsAccumulator read(final ObjectDataInput in) throws IOException {
+    final byte[] byteArray = in.readByteArray();
+    final Stats deserializedStats = Stats.fromByteArray(byteArray);
+    final StatsAccumulator accumulator = new StatsAccumulator();
+    accumulator.addAll(deserializedStats);
+    return accumulator;
+  }
+
+}
diff --git a/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/uc2specifics/StatsAccumulatorSupplier.java b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/uc2specifics/StatsAccumulatorSupplier.java
new file mode 100644
index 0000000000000000000000000000000000000000..f4d203f03185cda712a5280634d8d3858c02f30d
--- /dev/null
+++ b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/uc2specifics/StatsAccumulatorSupplier.java
@@ -0,0 +1,22 @@
+package rocks.theodolite.benchmarks.uc2.hazelcastjet.uc2specifics;
+
+import com.google.common.math.StatsAccumulator;
+import com.hazelcast.function.SupplierEx;
+
+/**
+ * Supplies a StatsAccumulator. Is used in the aggregation operation of the Hazelcast Jet
+ * implementation for UC2.
+ */
+public class StatsAccumulatorSupplier implements SupplierEx<StatsAccumulator> {
+
+  private static final long serialVersionUID = -656395626316842910L; // NOPMD
+
+  /**
+   * Gets a StatsAccumulator.
+   */
+  @Override
+  public StatsAccumulator getEx() throws Exception {
+    return new StatsAccumulator();
+  }
+
+}
diff --git a/theodolite-benchmarks/uc2-hazelcastjet/src/main/resources/META-INF/application.properties b/theodolite-benchmarks/uc2-hazelcastjet/src/main/resources/META-INF/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..e3371cc87e20e85e6e8c327955537e6e49dab86e
--- /dev/null
+++ b/theodolite-benchmarks/uc2-hazelcastjet/src/main/resources/META-INF/application.properties
@@ -0,0 +1,8 @@
+application.name=theodolite-uc1-application
+application.version=0.0.1
+
+kafka.bootstrap.servers=localhost:9092
+kafka.input.topic=input
+
+schema.registry.url=http://localhost:8081
+
diff --git a/theodolite-benchmarks/uc2-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2PipelineTest.java b/theodolite-benchmarks/uc2-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2PipelineTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ff72b9558f43334feb8846d50bef2c6714d9404a
--- /dev/null
+++ b/theodolite-benchmarks/uc2-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2PipelineTest.java
@@ -0,0 +1,108 @@
+package rocks.theodolite.benchmarks.uc2.hazelcastjet;
+
+import com.hazelcast.jet.Jet;
+import com.hazelcast.jet.JetInstance;
+import com.hazelcast.jet.config.JetConfig;
+import com.hazelcast.jet.core.JetTestSupport;
+import com.hazelcast.jet.pipeline.Pipeline;
+import com.hazelcast.jet.pipeline.StreamSource;
+import com.hazelcast.jet.pipeline.StreamStage;
+import com.hazelcast.jet.pipeline.test.AssertionCompletedException;
+import com.hazelcast.jet.pipeline.test.Assertions;
+import com.hazelcast.jet.pipeline.test.TestSources;
+import com.hazelcast.jet.test.SerialTest;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.CompletionException;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * Test methods for the Hazelcast Jet Implementation of UC2.
+ */
+@Category(SerialTest.class)
+public class Uc2PipelineTest extends JetTestSupport {
+
+  JetInstance testInstance = null;
+  Pipeline testPipeline = null;
+  StreamStage<Entry<String, String>> uc2Topology = null;
+
+  /*
+   * Creates the JetInstance, defines a new Hazelcast Jet Pipeline and extends the UC2 topology.
+   * Allows for quick extension of tests.
+   */
+  @Before
+  public void buildUc2Pipeline() {
+
+    // Setup Configuration
+    int testItemsPerSecond = 1;
+    String testSensorName = "TEST-SENSOR";
+    Double testValueInW = 10.0;
+    int testWindowInMs = 5000;
+
+    // Create mock jet instance with configuration
+    final String testClusterName = randomName();
+    final JetConfig testJetConfig = new JetConfig();
+    testJetConfig.getHazelcastConfig().setClusterName(testClusterName);
+    this.testInstance = this.createJetMember(testJetConfig);
+
+    // Create a test source
+    final StreamSource<Entry<String, ActivePowerRecord>> testSource =
+        TestSources.itemStream(testItemsPerSecond, (timestamp, item) -> {
+          final ActivePowerRecord testRecord =
+              new ActivePowerRecord(testSensorName, timestamp, testValueInW);
+          final Entry<String, ActivePowerRecord> testEntry =
+              Map.entry(testSensorName, testRecord);
+          return testEntry;
+        });
+
+    // Create pipeline to test
+    Uc2PipelineBuilder pipelineBuilder = new Uc2PipelineBuilder();
+    this.testPipeline = Pipeline.create();
+    this.uc2Topology =
+        pipelineBuilder.extendUc2Topology(this.testPipeline, testSource, testWindowInMs);
+
+  }
+
+  /**
+   * Tests if no items reach the end before the first window ends.
+   */
+  @Test
+  public void testOutput() {
+
+    // Assertion Configuration
+    int timeout = 14;
+    String expectedOutput = "Stats{count=5, mean=10.0, populationStandardDeviation=0.0, min=10.0, max=10.0}";
+
+    // Assertion
+    this.uc2Topology.apply(Assertions.assertCollectedEventually(timeout,
+        collection -> Assert.assertTrue(
+            "Not the right amount items in Stats Object!",
+            collection.get(collection.size()-1).getValue().equals(expectedOutput))));
+
+    // Run the test!
+    try {
+      this.testInstance.newJob(this.testPipeline).join();
+      Assert.fail("Job should have completed with an AssertionCompletedException, "
+          + "but completed normally!");
+    } catch (final CompletionException e) {
+      final String errorMsg = e.getCause().getMessage();
+      Assert.assertTrue(
+          "Job was expected to complete with AssertionCompletedException, but completed with: "
+              + e.getCause(),
+          errorMsg.contains(AssertionCompletedException.class.getName()));
+    }
+
+  }
+
+  @After
+  public void after() {
+    // Shuts down all running Jet Instances
+    Jet.shutdownAll();
+  }
+
+}
diff --git a/theodolite-benchmarks/uc2-kstreams/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc2-kstreams/.settings/org.eclipse.jdt.ui.prefs
index 4d01df75552c562406705858b6368ecf59d6e82f..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc2-kstreams/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc2-kstreams/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,25 +12,72 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
 cleanup.remove_redundant_semicolons=true
@@ -37,6 +85,7 @@ cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,28 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
 org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -80,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -115,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc2-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc2-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/uc2-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/uc2-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/uc2-kstreams/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc2-kstreams/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/uc2-kstreams/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/uc2-kstreams/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc2-kstreams/build.gradle b/theodolite-benchmarks/uc2-kstreams/build.gradle
index 6688f229b3c57f95aaaf5f5cd4ca615db609277a..9712c51cc089a519660dc4c7cf8eddb282aa5131 100644
--- a/theodolite-benchmarks/uc2-kstreams/build.gradle
+++ b/theodolite-benchmarks/uc2-kstreams/build.gradle
@@ -2,4 +2,4 @@ plugins {
   id 'theodolite.kstreams'
 }
 
-mainClassName = "theodolite.uc2.application.HistoryService"
+mainClassName = "rocks.theodolite.benchmarks.uc2.kstreams.HistoryService"
diff --git a/theodolite-benchmarks/uc2-kstreams/src/main/java/theodolite/uc2/application/HistoryService.java b/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/HistoryService.java
similarity index 90%
rename from theodolite-benchmarks/uc2-kstreams/src/main/java/theodolite/uc2/application/HistoryService.java
rename to theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/HistoryService.java
index 1aa28400cc9d55c77518a880d8cc2f48a2823a6b..3b87053507a7739381482719acf317903fe2d361 100644
--- a/theodolite-benchmarks/uc2-kstreams/src/main/java/theodolite/uc2/application/HistoryService.java
+++ b/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/HistoryService.java
@@ -1,12 +1,11 @@
-package theodolite.uc2.application;
+package rocks.theodolite.benchmarks.uc2.kstreams;
 
 import java.time.Duration;
 import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import org.apache.commons.configuration2.Configuration;
 import org.apache.kafka.streams.KafkaStreams;
-import theodolite.commons.kafkastreams.ConfigurationKeys;
-import theodolite.uc2.streamprocessing.Uc2KafkaStreamsBuilder;
+import rocks.theodolite.benchmarks.commons.kstreams.ConfigurationKeys;
 import titan.ccp.common.configuration.ServiceConfigurations;
 
 /**
diff --git a/theodolite-benchmarks/uc2-kstreams/src/main/java/theodolite/uc2/streamprocessing/TopologyBuilder.java b/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/TopologyBuilder.java
similarity index 93%
rename from theodolite-benchmarks/uc2-kstreams/src/main/java/theodolite/uc2/streamprocessing/TopologyBuilder.java
rename to theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/TopologyBuilder.java
index eda7c495a2cff6d58b62a8a6a74ea8e1b2d89aca..ae17c83bc141ef6056d7f9f89738d1442ba4afed 100644
--- a/theodolite-benchmarks/uc2-kstreams/src/main/java/theodolite/uc2/streamprocessing/TopologyBuilder.java
+++ b/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/TopologyBuilder.java
@@ -1,4 +1,4 @@
-package theodolite.uc2.streamprocessing;
+package rocks.theodolite.benchmarks.uc2.kstreams;
 
 import com.google.common.math.Stats;
 import java.time.Duration;
@@ -13,7 +13,7 @@ import org.apache.kafka.streams.kstream.Produced;
 import org.apache.kafka.streams.kstream.TimeWindows;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import theodolite.uc2.streamprocessing.util.StatsFactory;
+import rocks.theodolite.benchmarks.uc2.kstreams.util.StatsFactory;
 import titan.ccp.common.kafka.GenericSerde;
 import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory;
 import titan.ccp.model.records.ActivePowerRecord;
@@ -53,7 +53,7 @@ public class TopologyBuilder {
             Consumed.with(Serdes.String(),
                 this.srAvroSerdeFactory.<ActivePowerRecord>forValues()))
         .groupByKey()
-        .windowedBy(TimeWindows.of(this.duration))
+        .windowedBy(TimeWindows.ofSizeWithNoGrace(this.duration))
         // .aggregate(
         // () -> 0.0,
         // (key, activePowerRecord, agg) -> agg + activePowerRecord.getValueInW(),
diff --git a/theodolite-benchmarks/uc2-kstreams/src/main/java/theodolite/uc2/streamprocessing/Uc2KafkaStreamsBuilder.java b/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/Uc2KafkaStreamsBuilder.java
similarity index 91%
rename from theodolite-benchmarks/uc2-kstreams/src/main/java/theodolite/uc2/streamprocessing/Uc2KafkaStreamsBuilder.java
rename to theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/Uc2KafkaStreamsBuilder.java
index 1d6019f27cb78f6643e111095edbbdd9f6c03e1b..9db55ef921e44ac6ebb8b31ca58c13862c33ddcb 100644
--- a/theodolite-benchmarks/uc2-kstreams/src/main/java/theodolite/uc2/streamprocessing/Uc2KafkaStreamsBuilder.java
+++ b/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/Uc2KafkaStreamsBuilder.java
@@ -1,11 +1,11 @@
-package theodolite.uc2.streamprocessing;
+package rocks.theodolite.benchmarks.uc2.kstreams;
 
 import java.time.Duration;
 import java.util.Objects;
 import java.util.Properties;
 import org.apache.commons.configuration2.Configuration;
 import org.apache.kafka.streams.Topology;
-import theodolite.commons.kafkastreams.KafkaStreamsBuilder;
+import rocks.theodolite.benchmarks.commons.kstreams.KafkaStreamsBuilder;
 import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory;
 
 /**
diff --git a/theodolite-benchmarks/uc2-kstreams/src/main/java/theodolite/uc2/streamprocessing/util/StatsFactory.java b/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/util/StatsFactory.java
similarity index 90%
rename from theodolite-benchmarks/uc2-kstreams/src/main/java/theodolite/uc2/streamprocessing/util/StatsFactory.java
rename to theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/util/StatsFactory.java
index e4aff4fc80cea24c20be537f6aa5cda7c2be909a..8e43bf7e776222dd1269b5c4bcd0b330fec7f005 100644
--- a/theodolite-benchmarks/uc2-kstreams/src/main/java/theodolite/uc2/streamprocessing/util/StatsFactory.java
+++ b/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/util/StatsFactory.java
@@ -1,4 +1,4 @@
-package theodolite.uc2.streamprocessing.util;
+package rocks.theodolite.benchmarks.uc2.kstreams.util;
 
 import com.google.common.math.Stats;
 import com.google.common.math.StatsAccumulator;
diff --git a/theodolite-benchmarks/uc2-load-generator/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc2-load-generator/.settings/org.eclipse.jdt.ui.prefs
index 4d01df75552c562406705858b6368ecf59d6e82f..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc2-load-generator/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc2-load-generator/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,25 +12,72 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
 cleanup.remove_redundant_semicolons=true
@@ -37,6 +85,7 @@ cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,28 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
 org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -80,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -115,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc2-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc2-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/uc2-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/uc2-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/uc2-load-generator/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc2-load-generator/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/uc2-load-generator/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/uc2-load-generator/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc2-load-generator/build.gradle b/theodolite-benchmarks/uc2-load-generator/build.gradle
index 1954fe5cbfd62d26f27c59be486a516c91892e18..0e45bc209f75eb2171d834cbc564d216c78fb126 100644
--- a/theodolite-benchmarks/uc2-load-generator/build.gradle
+++ b/theodolite-benchmarks/uc2-load-generator/build.gradle
@@ -2,4 +2,4 @@ plugins {
   id 'theodolite.load-generator'
 }
 
-mainClassName = "theodolite.uc2.workloadgenerator.LoadGenerator"
+mainClassName = "rocks.theodolite.benchmarks.uc2.loadgenerator.LoadGenerator"
diff --git a/theodolite-benchmarks/uc2-load-generator/src/main/java/theodolite/uc2/workloadgenerator/LoadGenerator.java b/theodolite-benchmarks/uc2-load-generator/src/main/java/rocks/theodolite/benchmarks/uc2/loadgenerator/LoadGenerator.java
similarity index 73%
rename from theodolite-benchmarks/uc2-load-generator/src/main/java/theodolite/uc2/workloadgenerator/LoadGenerator.java
rename to theodolite-benchmarks/uc2-load-generator/src/main/java/rocks/theodolite/benchmarks/uc2/loadgenerator/LoadGenerator.java
index 2c5b59bc19f703c4216bc02920b62bcf9da5d5fb..f148dc69e1a495d00044126c7cf7f99ba97066f1 100644
--- a/theodolite-benchmarks/uc2-load-generator/src/main/java/theodolite/uc2/workloadgenerator/LoadGenerator.java
+++ b/theodolite-benchmarks/uc2-load-generator/src/main/java/rocks/theodolite/benchmarks/uc2/loadgenerator/LoadGenerator.java
@@ -1,4 +1,4 @@
-package theodolite.uc2.workloadgenerator;
+package rocks.theodolite.benchmarks.uc2.loadgenerator;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -14,6 +14,6 @@ public final class LoadGenerator {
 
   public static void main(final String[] args) {
     LOGGER.info("Start workload generator for use case UC2");
-    theodolite.commons.workloadgeneration.LoadGenerator.fromEnvironment().run();
+    rocks.theodolite.benchmarks.loadgenerator.LoadGenerator.fromEnvironment().run();
   }
 }
diff --git a/theodolite-benchmarks/uc3-beam-flink/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc3-beam-flink/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/uc3-beam-flink/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc3-beam-flink/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc3-beam-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc3-beam-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc3-beam-flink/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc3-beam-flink/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc3-beam-flink/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc3-beam-flink/build.gradle b/theodolite-benchmarks/uc3-beam-flink/build.gradle
index 8f047c6dce50636f01a7cdf645722aa5f7ac9ce9..c2fe5c11b0e24ecfa322d3f825261d2c60d650c4 100644
--- a/theodolite-benchmarks/uc3-beam-flink/build.gradle
+++ b/theodolite-benchmarks/uc3-beam-flink/build.gradle
@@ -2,11 +2,18 @@ plugins {
   id 'theodolite.beam.flink'
 }
 
-
 dependencies {
   implementation project(':uc3-beam')
 }
 
+sourceSets {
+  main {
+    resources {
+      srcDirs += [
+        project(':uc3-beam').sourceSets.main.resources
+      ]
+    }
+  }
+}
 
-// This is the path of the main class, stored within ./src/main/java/
-mainClassName = 'application.Uc3BeamFlink'
+mainClassName = 'rocks.theodolite.benchmarks.uc3.beam.flink.Uc3BeamFlink'
diff --git a/theodolite-benchmarks/uc3-beam-flink/src/main/java/application/Uc3BeamFlink.java b/theodolite-benchmarks/uc3-beam-flink/src/main/java/rocks/theodolite/benchmarks/uc3/beam/flink/Uc3BeamFlink.java
similarity index 59%
rename from theodolite-benchmarks/uc3-beam-flink/src/main/java/application/Uc3BeamFlink.java
rename to theodolite-benchmarks/uc3-beam-flink/src/main/java/rocks/theodolite/benchmarks/uc3/beam/flink/Uc3BeamFlink.java
index 18532b2655fcc6c24dad5f2fca87607c0b5d2e54..f4f4563925ede4d61edcaab29c3d6e7aed0b5e9c 100644
--- a/theodolite-benchmarks/uc3-beam-flink/src/main/java/application/Uc3BeamFlink.java
+++ b/theodolite-benchmarks/uc3-beam-flink/src/main/java/rocks/theodolite/benchmarks/uc3/beam/flink/Uc3BeamFlink.java
@@ -1,7 +1,8 @@
-package application;
+package rocks.theodolite.benchmarks.uc3.beam.flink;
 
 import org.apache.beam.runners.flink.FlinkRunner;
-import theodolite.commons.beam.AbstractBeamService;
+import rocks.theodolite.benchmarks.commons.beam.BeamService;
+import rocks.theodolite.benchmarks.uc3.beam.PipelineFactory;
 
 /**
  * Implementation of the use case Aggregation based on Time Attributes using Apache Beam with the
@@ -12,28 +13,15 @@ import theodolite.commons.beam.AbstractBeamService;
  * ${workspace_loc:/uc4-application-samza/eclipseConsoleLogs.log} as Output File under Standard
  * Input Output in Common in the Run Configuration Start via Eclipse Run.
  */
-public final class Uc3BeamFlink extends AbstractBeamService {
+public final class Uc3BeamFlink {
 
-  /**
-   * Private constructor to avoid instantiation.
-   */
-  private Uc3BeamFlink(final String[] args) { //NOPMD
-    super(args);
-    this.options.setRunner(FlinkRunner.class);
-  }
+  private Uc3BeamFlink() {}
 
   /**
    * Start running this microservice.
    */
   public static void main(final String[] args) {
-
-    final Uc3BeamFlink uc3BeamFlink = new Uc3BeamFlink(args);
-
-    final Uc3BeamPipeline pipeline =
-        new Uc3BeamPipeline(uc3BeamFlink.options, uc3BeamFlink.getConfig());
-
-    pipeline.run().waitUntilFinish();
+    new BeamService(PipelineFactory.factory(), FlinkRunner.class, args).runStandalone();
   }
-
 }
 
diff --git a/theodolite-benchmarks/uc3-beam-samza/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc3-beam-samza/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/uc3-beam-samza/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc3-beam-samza/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc3-beam-samza/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc3-beam-samza/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc3-beam-samza/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc3-beam-samza/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc3-beam-samza/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc3-beam-samza/Dockerfile b/theodolite-benchmarks/uc3-beam-samza/Dockerfile
index d3e860bd72c54121d616bc5562d519e6e1e21dec..54979b8e1fa8aa9ac7d073302301bd10cbff5f34 100644
--- a/theodolite-benchmarks/uc3-beam-samza/Dockerfile
+++ b/theodolite-benchmarks/uc3-beam-samza/Dockerfile
@@ -5,4 +5,4 @@ ENV MAX_SOURCE_PARALLELISM=1024
 ADD build/distributions/uc3-beam-samza.tar /
 ADD samza-standalone.properties /
 
-CMD /uc3-beam-samza/bin/uc3-beam-samza --configFactory=org.apache.samza.config.factories.PropertiesConfigFactory --configFilePath=samza-standalone.properties --samzaExecutionEnvironment=STANDALONE --maxSourceParallelism=$MAX_SOURCE_PARALLELISM --enableMetrics=false --configOverride="{\"job.coordinator.zk.connect\":\"$SAMZA_JOB_COORDINATOR_ZK_CONNECT\"}"
+CMD /uc3-beam-samza/bin/uc3-beam-samza --configFilePath=samza-standalone.properties --samzaExecutionEnvironment=STANDALONE --maxSourceParallelism=$MAX_SOURCE_PARALLELISM --enableMetrics=false --configOverride="{\"job.coordinator.zk.connect\":\"$SAMZA_JOB_COORDINATOR_ZK_CONNECT\"}"
diff --git a/theodolite-benchmarks/uc3-beam-samza/build.gradle b/theodolite-benchmarks/uc3-beam-samza/build.gradle
index 513b850330f4f71f440ad5da4ecea95f092f5ccc..b5d47d82b9c6056492ec7c21aebd691f4e335ddb 100644
--- a/theodolite-benchmarks/uc3-beam-samza/build.gradle
+++ b/theodolite-benchmarks/uc3-beam-samza/build.gradle
@@ -2,9 +2,18 @@ plugins {
   id 'theodolite.beam.samza'
 }
 
-
 dependencies {
   implementation project(':uc3-beam')
 }
 
-mainClassName = "application.Uc3BeamSamza"
\ No newline at end of file
+sourceSets {
+  main {
+    resources {
+      srcDirs += [
+        project(':uc3-beam').sourceSets.main.resources
+      ]
+    }
+  }
+}
+
+mainClassName = "rocks.theodolite.benchmarks.uc3.beam.samza.Uc3BeamSamza"
diff --git a/theodolite-benchmarks/uc3-beam-samza/src/main/java/application/Uc3BeamSamza.java b/theodolite-benchmarks/uc3-beam-samza/src/main/java/rocks/theodolite/benchmarks/uc3/beam/samza/Uc3BeamSamza.java
similarity index 59%
rename from theodolite-benchmarks/uc3-beam-samza/src/main/java/application/Uc3BeamSamza.java
rename to theodolite-benchmarks/uc3-beam-samza/src/main/java/rocks/theodolite/benchmarks/uc3/beam/samza/Uc3BeamSamza.java
index 913293bd02cb16e14ee9d94ea0e161c74853e72a..247cd99becff8a200185c8fa40efb49bf31a6806 100644
--- a/theodolite-benchmarks/uc3-beam-samza/src/main/java/application/Uc3BeamSamza.java
+++ b/theodolite-benchmarks/uc3-beam-samza/src/main/java/rocks/theodolite/benchmarks/uc3/beam/samza/Uc3BeamSamza.java
@@ -1,7 +1,8 @@
-package application;
+package rocks.theodolite.benchmarks.uc3.beam.samza;
 
 import org.apache.beam.runners.samza.SamzaRunner;
-import theodolite.commons.beam.AbstractBeamService;
+import rocks.theodolite.benchmarks.commons.beam.BeamService;
+import rocks.theodolite.benchmarks.uc3.beam.PipelineFactory;
 
 /**
  * Implementation of the use case Aggregation based on Time Attributes using Apache Beam with the
@@ -12,27 +13,15 @@ import theodolite.commons.beam.AbstractBeamService;
  * ${workspace_loc:/uc4-application-samza/eclipseConsoleLogs.log} as Output File under Standard
  * Input Output in Common in the Run Configuration Start via Eclipse Run.
  */
-public final class Uc3BeamSamza extends AbstractBeamService {
+public final class Uc3BeamSamza {
 
-  /**
-   * Private constructor to avoid instantiation.
-   */
-  private Uc3BeamSamza(final String[] args) { //NOPMD
-    super(args);
-    this.options.setRunner(SamzaRunner.class);
-  }
+  private Uc3BeamSamza() {}
 
   /**
    * Start running this microservice.
    */
   public static void main(final String[] args) {
-
-    final Uc3BeamSamza uc3BeamSamza = new Uc3BeamSamza(args);
-
-    final Uc3BeamPipeline pipeline =
-        new Uc3BeamPipeline(uc3BeamSamza.options, uc3BeamSamza.getConfig());
-
-    pipeline.run().waitUntilFinish();
+    new BeamService(PipelineFactory.factory(), SamzaRunner.class, args).runStandalone();
   }
 
 }
diff --git a/theodolite-benchmarks/uc3-beam-samza/src/main/resources/META-INF/application.properties b/theodolite-benchmarks/uc3-beam-samza/src/main/resources/META-INF/application.properties
deleted file mode 100644
index 2db723927eaee10d39e02a6b2d369a06af7711fc..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc3-beam-samza/src/main/resources/META-INF/application.properties
+++ /dev/null
@@ -1,22 +0,0 @@
-application.name=theodolite-uc3-application
-application.version=0.0.1
-
-kafka.bootstrap.servers=localhost:9092
-kafka.input.topic=input
-kafka.output.topic=output
-kafka.window.duration.minutes=1
-
-schema.registry.url=http://localhost:8081
-
-aggregation.duration.days=30
-aggregation.advance.days=1
-
-trigger.interval=15
-
-num.threads=1
-commit.interval.ms=1000
-cache.max.bytes.buffering=-1
-
-specific.avro.reader=True
-enable.auto.commit.config=True
-auto.offset.reset.config=earliest
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc3-beam/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc3-beam/.settings/org.eclipse.jdt.ui.prefs
index d71754b65d8da3cee7e6e440f49aa833ddabae10..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc3-beam/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc3-beam/.settings/org.eclipse.jdt.ui.prefs
@@ -105,6 +105,7 @@ cleanup.strictly_equal_or_different=false
 cleanup.stringbuffer_to_stringbuilder=false
 cleanup.stringbuilder=false
 cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
 cleanup.substring=false
 cleanup.switch=false
 cleanup.system_property=false
@@ -144,6 +145,7 @@ org.eclipse.jdt.ui.ignorelowercasenames=true
 org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
 sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
@@ -165,11 +167,11 @@ sp_cleanup.boolean_literal=false
 sp_cleanup.boolean_value_rather_than_comparison=false
 sp_cleanup.break_loop=false
 sp_cleanup.collection_cloning=false
-sp_cleanup.comparing_on_criteria=false
+sp_cleanup.comparing_on_criteria=true
 sp_cleanup.comparison_statement=false
 sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
-sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.convert_to_enhanced_for_loop=true
 sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
 sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
@@ -190,7 +192,7 @@ sp_cleanup.invert_equals=false
 sp_cleanup.join=false
 sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
-sp_cleanup.make_parameters_final=false
+sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
@@ -227,14 +229,14 @@ sp_cleanup.redundant_comparator=false
 sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
 sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
-sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
 sp_cleanup.remove_unused_local_variables=false
 sp_cleanup.remove_unused_private_fields=true
@@ -251,7 +253,8 @@ sp_cleanup.static_inner_class=false
 sp_cleanup.strictly_equal_or_different=false
 sp_cleanup.stringbuffer_to_stringbuilder=false
 sp_cleanup.stringbuilder=false
-sp_cleanup.stringbuilder_for_local_vars=true
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
 sp_cleanup.substring=false
 sp_cleanup.switch=false
 sp_cleanup.system_property=false
@@ -261,7 +264,7 @@ sp_cleanup.system_property_file_separator=false
 sp_cleanup.system_property_line_separator=false
 sp_cleanup.system_property_path_separator=false
 sp_cleanup.ternary_operator=false
-sp_cleanup.try_with_resource=true
+sp_cleanup.try_with_resource=false
 sp_cleanup.unlooped_while=false
 sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
@@ -278,6 +281,6 @@ sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
 sp_cleanup.use_unboxing=false
 sp_cleanup.use_var=false
-sp_cleanup.useless_continue=false
-sp_cleanup.useless_return=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
 sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc3-beam/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc3-beam/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc3-beam/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc3-beam/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc3-beam/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc3-beam/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc3-beam/src/main/java/application/Uc3BeamPipeline.java b/theodolite-benchmarks/uc3-beam/src/main/java/application/Uc3BeamPipeline.java
deleted file mode 100644
index c402271777dd63026e1f1fb36855dad1a72e1136..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc3-beam/src/main/java/application/Uc3BeamPipeline.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package application;
-
-import com.google.common.math.Stats;
-import com.google.common.math.StatsAccumulator;
-import java.util.Map;
-import org.apache.beam.sdk.coders.AvroCoder;
-import org.apache.beam.sdk.coders.CoderRegistry;
-import org.apache.beam.sdk.coders.KvCoder;
-import org.apache.beam.sdk.coders.SerializableCoder;
-import org.apache.beam.sdk.options.PipelineOptions;
-import org.apache.beam.sdk.transforms.Combine;
-import org.apache.beam.sdk.transforms.MapElements;
-import org.apache.beam.sdk.transforms.windowing.AfterProcessingTime;
-import org.apache.beam.sdk.transforms.windowing.AfterWatermark;
-import org.apache.beam.sdk.transforms.windowing.SlidingWindows;
-import org.apache.beam.sdk.transforms.windowing.Window;
-import org.apache.beam.sdk.values.KV;
-import org.apache.commons.configuration2.Configuration;
-import org.apache.kafka.common.serialization.StringSerializer;
-import org.joda.time.Duration;
-import theodolite.commons.beam.AbstractPipeline;
-import theodolite.commons.beam.ConfigurationKeys;
-import theodolite.commons.beam.kafka.KafkaActivePowerTimestampReader;
-import theodolite.commons.beam.kafka.KafkaWriterTransformation;
-import titan.ccp.model.records.ActivePowerRecord;
-
-
-/**
- * Implementation of the use case Aggregation based on Time Attributes using Apache Beam.
- */
-public final class Uc3BeamPipeline extends AbstractPipeline {
-
-  protected Uc3BeamPipeline(final PipelineOptions options, final Configuration config) {
-    super(options, config);
-    // Additional needed variables
-    final String outputTopic = config.getString(ConfigurationKeys.KAFKA_OUTPUT_TOPIC);
-
-    final Duration duration =
-        Duration.standardDays(config.getInt(ConfigurationKeys.AGGREGATION_DURATION_DAYS));
-    final Duration aggregationAdvanceDuration =
-        Duration.standardDays(config.getInt(ConfigurationKeys.AGGREGATION_ADVANCE_DAYS));
-    final Duration triggerDelay =
-        Duration.standardSeconds(config.getInt(ConfigurationKeys.TRIGGER_INTERVAL));
-
-    // Build Kafka configuration
-    final Map<String, Object> consumerConfig = this.buildConsumerConfig();
-
-    // Set Coders for classes that will be distributed
-    final CoderRegistry cr = this.getCoderRegistry();
-    registerCoders(cr);
-
-    // Read from Kafka
-    final KafkaActivePowerTimestampReader kafka =
-        new KafkaActivePowerTimestampReader(this.bootstrapServer, this.inputTopic, consumerConfig);
-
-    // Map the time format
-    final MapTimeFormat mapTimeFormat = new MapTimeFormat();
-
-    // Get the stats per HourOfDay
-    final HourOfDayWithStats hourOfDayWithStats = new HourOfDayWithStats();
-
-    // Write to Kafka
-    final KafkaWriterTransformation<String> kafkaWriter =
-        new KafkaWriterTransformation<>(this.bootstrapServer, outputTopic, StringSerializer.class);
-
-    this.apply(kafka)
-        // Map to correct time format
-        .apply(MapElements.via(mapTimeFormat))
-        // Apply a sliding window
-        .apply(Window
-            .<KV<HourOfDayKey, ActivePowerRecord>>into(
-                SlidingWindows.of(duration).every(aggregationAdvanceDuration))
-            .triggering(AfterWatermark.pastEndOfWindow()
-                .withEarlyFirings(
-                    AfterProcessingTime.pastFirstElementInPane().plusDelayOf(triggerDelay)))
-            .withAllowedLateness(Duration.ZERO)
-            .accumulatingFiredPanes())
-
-        // Aggregate per window for every key
-        .apply(Combine.<HourOfDayKey, ActivePowerRecord, Stats>perKey(new StatsAggregation()))
-        .setCoder(KvCoder.of(new HourOfDaykeyCoder(), SerializableCoder.of(Stats.class)))
-
-        // Map into correct output format
-        .apply(MapElements.via(hourOfDayWithStats))
-        // Write to Kafka
-        .apply(kafkaWriter);
-  }
-
-
-  /**
-   * Registers all Coders for all needed Coders.
-   *
-   * @param cr CoderRegistry.
-   */
-  private static void registerCoders(final CoderRegistry cr) {
-    cr.registerCoderForClass(ActivePowerRecord.class, AvroCoder.of(ActivePowerRecord.SCHEMA$));
-    cr.registerCoderForClass(HourOfDayKey.class, new HourOfDaykeyCoder());
-    cr.registerCoderForClass(StatsAggregation.class, SerializableCoder.of(StatsAggregation.class));
-    cr.registerCoderForClass(StatsAccumulator.class, AvroCoder.of(StatsAccumulator.class));
-  }
-}
-
diff --git a/theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDayKey.java b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKey.java
similarity index 77%
rename from theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDayKey.java
rename to theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKey.java
index 6db59dd65ee494157400b0f4c6eafbdd7655d402..bde85327cfa8daa82bd3b29db82a96b06e1621f4 100644
--- a/theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDayKey.java
+++ b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKey.java
@@ -1,13 +1,8 @@
-package application;
-
-import org.apache.beam.sdk.coders.AvroCoder;
-import org.apache.beam.sdk.coders.DefaultCoder;
-
+package rocks.theodolite.benchmarks.uc3.beam;
 
 /**
  * Composed key of an hour of the day and a sensor id.
  */
-@DefaultCoder(AvroCoder.class)
 public class HourOfDayKey {
 
   private final int hourOfDay;
diff --git a/theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDaykeyCoder.java b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKeyCoder.java
similarity index 90%
rename from theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDaykeyCoder.java
rename to theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKeyCoder.java
index 196408263ec29a1ec9b45375dd0b53a18e8f60b3..4189761c05981815290c5d2779ad78e94fcb51c0 100644
--- a/theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDaykeyCoder.java
+++ b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKeyCoder.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc3.beam;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -12,9 +12,9 @@ import org.apache.beam.sdk.coders.CoderException;
 import org.apache.kafka.common.serialization.Serde;
 
 /**
- * Wrapper Class that encapsulates a HourOfDayKeySerde in a org.apache.beam.sdk.coders.Coder.
+ * Wrapper Class that encapsulates a {@link HourOfDayKeySerde} in a {@link Coder}.
  */
-public class HourOfDaykeyCoder extends Coder<HourOfDayKey> implements Serializable {
+public class HourOfDayKeyCoder extends Coder<HourOfDayKey> implements Serializable {
   public static final long serialVersionUID = 4444444;
   private static final boolean DETERMINISTIC = true;
   private static final int VALUE_SIZE = 4;
diff --git a/theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDayKeyFactory.java b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKeyFactory.java
similarity index 92%
rename from theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDayKeyFactory.java
rename to theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKeyFactory.java
index b993a0199bc13e9b416f9b9cb77a27635d7fe1e1..a685f324103b23a79fd53bda7eae55d798c40e1d 100644
--- a/theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDayKeyFactory.java
+++ b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKeyFactory.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc3.beam;
 
 import java.io.Serializable;
 import java.time.LocalDateTime;
diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/HourOfDayKeySerde.java b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKeySerde.java
similarity index 95%
rename from theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/HourOfDayKeySerde.java
rename to theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKeySerde.java
index 6855907e7f357d681c3bd9a6054bf15ad29711ed..1c09d7d508888b48c2a509d83f55ff49ca967f17 100644
--- a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/HourOfDayKeySerde.java
+++ b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKeySerde.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.streamprocessing;
+package rocks.theodolite.benchmarks.uc3.beam;
 
 import org.apache.kafka.common.serialization.Serde;
 import titan.ccp.common.kafka.simpleserdes.BufferSerde;
diff --git a/theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDayWithStats.java b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayWithStats.java
similarity index 93%
rename from theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDayWithStats.java
rename to theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayWithStats.java
index 46232b3f13601d77f6cb7b13ea0bcdc31290357a..0d9aa6ab0342db1d92cfedc874adb8c454d00ef8 100644
--- a/theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDayWithStats.java
+++ b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayWithStats.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc3.beam;
 
 import com.google.common.math.Stats;
 import org.apache.beam.sdk.transforms.SimpleFunction;
diff --git a/theodolite-benchmarks/uc3-beam/src/main/java/application/MapTimeFormat.java b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/MapTimeFormat.java
similarity index 73%
rename from theodolite-benchmarks/uc3-beam/src/main/java/application/MapTimeFormat.java
rename to theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/MapTimeFormat.java
index 7d8897fb0fd76cd4eb145da6a7ce031f9f45d396..3c0d7acdbeccfaf03aac70df478e3db6dd1378e4 100644
--- a/theodolite-benchmarks/uc3-beam/src/main/java/application/MapTimeFormat.java
+++ b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/MapTimeFormat.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc3.beam;
 
 import java.time.Instant;
 import java.time.LocalDateTime;
@@ -8,7 +8,7 @@ import org.apache.beam.sdk.values.KV;
 import titan.ccp.model.records.ActivePowerRecord;
 
 /**
- * Changes the time format to us europe/paris time.
+ * Changes the time format to us Europe/Paris time.
  */
 public class MapTimeFormat
     extends SimpleFunction<KV<String, ActivePowerRecord>, KV<HourOfDayKey, ActivePowerRecord>> {
@@ -17,11 +17,11 @@ public class MapTimeFormat
   private final ZoneId zone = ZoneId.of("Europe/Paris");
 
   @Override
-  public KV<HourOfDayKey, ActivePowerRecord> apply(
-      final KV<String, ActivePowerRecord> kv) {
+  public KV<HourOfDayKey, ActivePowerRecord> apply(final KV<String, ActivePowerRecord> kv) {
     final Instant instant = Instant.ofEpochMilli(kv.getValue().getTimestamp());
     final LocalDateTime dateTime = LocalDateTime.ofInstant(instant, this.zone);
-    return KV.of(this.keyFactory.createKey(kv.getValue().getIdentifier(), dateTime),
+    return KV.of(
+        this.keyFactory.createKey(kv.getValue().getIdentifier(), dateTime),
         kv.getValue());
   }
 }
diff --git a/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/PipelineFactory.java b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/PipelineFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c766e41254555647dd7ef1eed0417613b7c1629
--- /dev/null
+++ b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/PipelineFactory.java
@@ -0,0 +1,111 @@
+package rocks.theodolite.benchmarks.uc3.beam;
+
+import com.google.common.math.Stats;
+import com.google.common.math.StatsAccumulator;
+import java.util.function.Function;
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.coders.AvroCoder;
+import org.apache.beam.sdk.coders.CoderRegistry;
+import org.apache.beam.sdk.coders.KvCoder;
+import org.apache.beam.sdk.coders.SerializableCoder;
+import org.apache.beam.sdk.options.PipelineOptions;
+import org.apache.beam.sdk.transforms.Combine;
+import org.apache.beam.sdk.transforms.MapElements;
+import org.apache.beam.sdk.transforms.windowing.AfterProcessingTime;
+import org.apache.beam.sdk.transforms.windowing.AfterWatermark;
+import org.apache.beam.sdk.transforms.windowing.SlidingWindows;
+import org.apache.beam.sdk.transforms.windowing.Window;
+import org.apache.beam.sdk.values.KV;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.kafka.common.serialization.StringSerializer;
+import org.joda.time.Duration;
+import rocks.theodolite.benchmarks.commons.beam.AbstractPipelineFactory;
+import rocks.theodolite.benchmarks.commons.beam.ConfigurationKeys;
+import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaActivePowerTimestampReader;
+import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaWriterTransformation;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * {@link AbstractPipelineFactory} for UC3.
+ */
+public class PipelineFactory extends AbstractPipelineFactory {
+
+  public PipelineFactory(final Configuration configuration) {
+    super(configuration);
+  }
+
+  @Override
+  protected void expandOptions(final PipelineOptions options) {
+    // No options to set
+  }
+
+  @Override
+  protected void constructPipeline(final Pipeline pipeline) {
+    final String outputTopic = this.config.getString(ConfigurationKeys.KAFKA_OUTPUT_TOPIC);
+
+    final Duration duration =
+        Duration.standardDays(this.config.getInt(ConfigurationKeys.AGGREGATION_DURATION_DAYS));
+    final Duration aggregationAdvanceDuration =
+        Duration.standardDays(this.config.getInt(ConfigurationKeys.AGGREGATION_ADVANCE_DAYS));
+    final Duration triggerDelay =
+        Duration.standardSeconds(this.config.getInt(ConfigurationKeys.TRIGGER_INTERVAL));
+
+    // Read from Kafka
+    final KafkaActivePowerTimestampReader kafkaReader = super.buildKafkaReader();
+
+    // Map the time format
+    final MapTimeFormat mapTimeFormat = new MapTimeFormat();
+
+    // Get the stats per HourOfDay
+    final HourOfDayWithStats hourOfDayWithStats = new HourOfDayWithStats();
+
+    // Write to Kafka
+    final String bootstrapServer = this.config.getString(ConfigurationKeys.KAFKA_BOOTSTRAP_SERVERS);
+    final KafkaWriterTransformation<String> kafkaWriter =
+        new KafkaWriterTransformation<>(bootstrapServer, outputTopic, StringSerializer.class);
+
+    pipeline.apply(kafkaReader)
+        // Map to correct time format
+        .apply(MapElements.via(mapTimeFormat))
+        // Apply a sliding window
+        .apply(Window
+            .<KV<HourOfDayKey, ActivePowerRecord>>into(
+                SlidingWindows.of(duration).every(aggregationAdvanceDuration))
+            .triggering(AfterWatermark.pastEndOfWindow()
+                .withEarlyFirings(
+                    AfterProcessingTime.pastFirstElementInPane().plusDelayOf(triggerDelay)))
+            .withAllowedLateness(Duration.ZERO)
+            .accumulatingFiredPanes())
+
+        // Aggregate per window for every key
+        .apply(Combine.perKey(new StatsAggregation()))
+        .setCoder(KvCoder.of(new HourOfDayKeyCoder(), SerializableCoder.of(Stats.class)))
+
+        // Map into correct output format
+        .apply(MapElements.via(hourOfDayWithStats))
+        // Write to Kafka
+        .apply(kafkaWriter);
+  }
+
+  @Override
+  protected void registerCoders(final CoderRegistry registry) {
+    registry.registerCoderForClass(
+        ActivePowerRecord.class,
+        // AvroCoder.of(ActivePowerRecord.SCHEMA$));
+        AvroCoder.of(ActivePowerRecord.class, false));
+    registry.registerCoderForClass(
+        HourOfDayKey.class,
+        new HourOfDayKeyCoder());
+    registry.registerCoderForClass(
+        StatsAggregation.class,
+        SerializableCoder.of(StatsAggregation.class));
+    registry.registerCoderForClass(
+        StatsAccumulator.class,
+        AvroCoder.of(StatsAccumulator.class));
+  }
+
+  public static Function<Configuration, AbstractPipelineFactory> factory() {
+    return config -> new PipelineFactory(config);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc3-beam/src/main/java/application/StatsAggregation.java b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/StatsAggregation.java
similarity index 96%
rename from theodolite-benchmarks/uc3-beam/src/main/java/application/StatsAggregation.java
rename to theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/StatsAggregation.java
index ee5cfc48bcd42dec41dd2030ad3f4a730fd6ac85..e479c0ab5e192f7e5239c100a05df454bd2973ad 100644
--- a/theodolite-benchmarks/uc3-beam/src/main/java/application/StatsAggregation.java
+++ b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/StatsAggregation.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc3.beam;
 
 import com.google.common.math.Stats;
 import com.google.common.math.StatsAccumulator;
diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/StatsKeyFactory.java b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/StatsKeyFactory.java
similarity index 87%
rename from theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/StatsKeyFactory.java
rename to theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/StatsKeyFactory.java
index 0e414c4a13f1cf7df1da5f0026b6de82e1c1c6ce..6f34a50ad171da7d595f23f9b81f4dabfe226fae 100644
--- a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/StatsKeyFactory.java
+++ b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/StatsKeyFactory.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.streamprocessing;
+package rocks.theodolite.benchmarks.uc3.beam;
 
 import java.time.LocalDateTime;
 
diff --git a/theodolite-benchmarks/uc3-beam-flink/src/main/resources/META-INF/application.properties b/theodolite-benchmarks/uc3-beam/src/main/resources/META-INF/application.properties
similarity index 79%
rename from theodolite-benchmarks/uc3-beam-flink/src/main/resources/META-INF/application.properties
rename to theodolite-benchmarks/uc3-beam/src/main/resources/META-INF/application.properties
index 2db723927eaee10d39e02a6b2d369a06af7711fc..0fe4b240d97f087f00c28430740488f7e01f1577 100644
--- a/theodolite-benchmarks/uc3-beam-flink/src/main/resources/META-INF/application.properties
+++ b/theodolite-benchmarks/uc3-beam/src/main/resources/META-INF/application.properties
@@ -17,6 +17,7 @@ num.threads=1
 commit.interval.ms=1000
 cache.max.bytes.buffering=-1
 
-specific.avro.reader=True
-enable.auto.commit.config=True
-auto.offset.reset.config=earliest
\ No newline at end of file
+specific.avro.reader=true
+enable.auto.commit=true
+max.poll.records=500
+auto.offset.reset=earliest
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc3-flink/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc3-flink/.settings/org.eclipse.jdt.ui.prefs
index 4d01df75552c562406705858b6368ecf59d6e82f..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc3-flink/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc3-flink/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,25 +12,72 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
 cleanup.remove_redundant_semicolons=true
@@ -37,6 +85,7 @@ cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,28 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
 org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -80,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -115,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc3-flink/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc3-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/uc3-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/uc3-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/uc3-flink/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc3-flink/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/uc3-flink/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/uc3-flink/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc3-flink/Dockerfile b/theodolite-benchmarks/uc3-flink/Dockerfile
index 34c6da692cb30b738adf47b9d4ca893e72f330e4..cef05c0296f55f0cf7391dd35dd1806ec0efa287 100644
--- a/theodolite-benchmarks/uc3-flink/Dockerfile
+++ b/theodolite-benchmarks/uc3-flink/Dockerfile
@@ -1,3 +1,3 @@
-FROM flink:1.12-scala_2.12-java11
+FROM flink:1.13-java11
 
 ADD build/libs/uc3-flink-all.jar /opt/flink/usrlib/artifacts/uc3-flink-all.jar
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc3-flink/build.gradle b/theodolite-benchmarks/uc3-flink/build.gradle
index b8bb79bc1d41627f57c3d9f3b897cbc4c260d620..b6eb067406400299dd3d40061f41b9bc414117b6 100644
--- a/theodolite-benchmarks/uc3-flink/build.gradle
+++ b/theodolite-benchmarks/uc3-flink/build.gradle
@@ -2,4 +2,4 @@ plugins {
   id 'theodolite.flink'
 }
 
-mainClassName = "theodolite.uc3.application.HistoryServiceFlinkJob"
+mainClassName = "rocks.theodolite.benchmarks.uc3.flink.HistoryServiceFlinkJob"
diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/ConfigurationKeys.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/ConfigurationKeys.java
similarity index 96%
rename from theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/ConfigurationKeys.java
rename to theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/ConfigurationKeys.java
index bc4e0b9d2d230026e9d2b6df0a11e4fb68380aed..980f07b9b1478bd2c5fa74c89d1aaff4c10f60df 100644
--- a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/ConfigurationKeys.java
+++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/ConfigurationKeys.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.application;
+package rocks.theodolite.benchmarks.uc3.flink;
 
 /**
  * Keys to access configuration parameters.
diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/HistoryServiceFlinkJob.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/HistoryServiceFlinkJob.java
similarity index 91%
rename from theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/HistoryServiceFlinkJob.java
rename to theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/HistoryServiceFlinkJob.java
index 091b25674a2a31671ca68bd2076c694da9533d77..4cf7ed080882e42bf488a8e6490c3eab463882b4 100644
--- a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/HistoryServiceFlinkJob.java
+++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/HistoryServiceFlinkJob.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.application;
+package rocks.theodolite.benchmarks.uc3.flink;
 
 import com.google.common.math.Stats;
 import java.time.Instant;
@@ -9,7 +9,6 @@ import org.apache.flink.api.common.typeinfo.Types;
 import org.apache.flink.api.java.functions.KeySelector;
 import org.apache.flink.api.java.tuple.Tuple2;
 import org.apache.flink.runtime.state.StateBackend;
-import org.apache.flink.streaming.api.TimeCharacteristic;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
 import org.apache.flink.streaming.api.windowing.assigners.SlidingEventTimeWindows;
 import org.apache.flink.streaming.api.windowing.time.Time;
@@ -18,13 +17,13 @@ import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer;
 import org.apache.kafka.common.serialization.Serdes;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import theodolite.commons.flink.KafkaConnectorFactory;
-import theodolite.commons.flink.StateBackends;
-import theodolite.commons.flink.serialization.StatsSerializer;
-import theodolite.uc3.application.util.HourOfDayKey;
-import theodolite.uc3.application.util.HourOfDayKeyFactory;
-import theodolite.uc3.application.util.HourOfDayKeySerde;
-import theodolite.uc3.application.util.StatsKeyFactory;
+import rocks.theodolite.benchmarks.commons.flink.KafkaConnectorFactory;
+import rocks.theodolite.benchmarks.commons.flink.StateBackends;
+import rocks.theodolite.benchmarks.commons.flink.serialization.StatsSerializer;
+import rocks.theodolite.benchmarks.uc3.flink.util.HourOfDayKey;
+import rocks.theodolite.benchmarks.uc3.flink.util.HourOfDayKeyFactory;
+import rocks.theodolite.benchmarks.uc3.flink.util.HourOfDayKeySerde;
+import rocks.theodolite.benchmarks.uc3.flink.util.StatsKeyFactory;
 import titan.ccp.common.configuration.ServiceConfigurations;
 import titan.ccp.model.records.ActivePowerRecord;
 
@@ -55,8 +54,6 @@ public final class HistoryServiceFlinkJob {
   }
 
   private void configureEnv() {
-    this.env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
-
     final boolean checkpointing = this.config.getBoolean(ConfigurationKeys.CHECKPOINTING, true);
     final int commitIntervalMs = this.config.getInt(ConfigurationKeys.COMMIT_INTERVAL_MS);
     if (checkpointing) {
diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/HourOfDayProcessWindowFunction.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/HourOfDayProcessWindowFunction.java
similarity index 89%
rename from theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/HourOfDayProcessWindowFunction.java
rename to theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/HourOfDayProcessWindowFunction.java
index 349c63413d0da792ad34e8ec8d94e7ff5dc06a42..9c70ef9dac3e7d000fa21a70b92109bc61156ab7 100644
--- a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/HourOfDayProcessWindowFunction.java
+++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/HourOfDayProcessWindowFunction.java
@@ -1,11 +1,11 @@
-package theodolite.uc3.application;
+package rocks.theodolite.benchmarks.uc3.flink;
 
 import com.google.common.math.Stats;
 import org.apache.flink.api.java.tuple.Tuple2;
 import org.apache.flink.streaming.api.functions.windowing.ProcessWindowFunction;
 import org.apache.flink.streaming.api.windowing.windows.TimeWindow;
 import org.apache.flink.util.Collector;
-import theodolite.uc3.application.util.HourOfDayKey;
+import rocks.theodolite.benchmarks.uc3.flink.util.HourOfDayKey;
 
 /**
  * A {@link ProcessWindowFunction} that forwards a computed {@link Stats} object along with its
diff --git a/theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/StatsAggregateFunction.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/StatsAggregateFunction.java
similarity index 90%
rename from theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/StatsAggregateFunction.java
rename to theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/StatsAggregateFunction.java
index 7bd090de819ce0c0c73687bd53a191b66ae31ed9..38d277dac28e88c82a38a1b56ef15cab2c00db14 100644
--- a/theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/StatsAggregateFunction.java
+++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/StatsAggregateFunction.java
@@ -1,9 +1,9 @@
-package theodolite.uc2.application;
+package rocks.theodolite.benchmarks.uc3.flink;
 
 import com.google.common.math.Stats;
 import com.google.common.math.StatsAccumulator;
 import org.apache.flink.api.common.functions.AggregateFunction;
-import theodolite.uc2.application.util.StatsFactory;
+import rocks.theodolite.benchmarks.uc3.flink.util.StatsFactory;
 import titan.ccp.model.records.ActivePowerRecord;
 
 /**
diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/HourOfDayKey.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayKey.java
similarity index 97%
rename from theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/HourOfDayKey.java
rename to theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayKey.java
index 5def88b404f23a59955ca2de42b91c22b7b1b53d..d5cf47bfbf9777dabd809eea8d7770946e39b8e0 100644
--- a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/HourOfDayKey.java
+++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayKey.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.application.util;
+package rocks.theodolite.benchmarks.uc3.flink.util;
 
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/HourOfDayKeyFactory.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayKeyFactory.java
similarity index 91%
rename from theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/HourOfDayKeyFactory.java
rename to theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayKeyFactory.java
index bd67b2508bc91a87635c52e95b963ed908ed92bf..91e4afb0423f16cd0dd3942301e2f6e51adcd402 100644
--- a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/HourOfDayKeyFactory.java
+++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayKeyFactory.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.application.util;
+package rocks.theodolite.benchmarks.uc3.flink.util;
 
 import java.io.Serializable;
 import java.time.LocalDateTime;
diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/HourOfDayKeySerde.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayKeySerde.java
similarity index 97%
rename from theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/HourOfDayKeySerde.java
rename to theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayKeySerde.java
index 6e3ae9f754d2b1d4ab10349040f0c9e51134c4f7..2c5bd40fe29f683693fb57bc679dd288e7d3bfb9 100644
--- a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/HourOfDayKeySerde.java
+++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayKeySerde.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.application.util;
+package rocks.theodolite.benchmarks.uc3.flink.util;
 
 import com.esotericsoftware.kryo.Kryo;
 import com.esotericsoftware.kryo.Serializer;
diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/HourOfDayRecordFactory.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayRecordFactory.java
similarity index 93%
rename from theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/HourOfDayRecordFactory.java
rename to theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayRecordFactory.java
index dfa9b95b08b95bf29621969c56a1e76cdcfc7877..5c52a446eac7f7ba39dfe12c247744054fd735d5 100644
--- a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/HourOfDayRecordFactory.java
+++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayRecordFactory.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.streamprocessing;
+package rocks.theodolite.benchmarks.uc3.flink.util;
 
 import com.google.common.math.Stats;
 import org.apache.kafka.streams.kstream.Windowed;
diff --git a/theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/util/StatsFactory.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/StatsFactory.java
similarity index 91%
rename from theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/util/StatsFactory.java
rename to theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/StatsFactory.java
index 9697108eb8dacabf925f06067199a41eb0658dbe..71955acdf9c81d71284e761cbdf151b5a2bb73ef 100644
--- a/theodolite-benchmarks/uc2-flink/src/main/java/theodolite/uc2/application/util/StatsFactory.java
+++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/StatsFactory.java
@@ -1,4 +1,4 @@
-package theodolite.uc2.application.util;
+package rocks.theodolite.benchmarks.uc3.flink.util;
 
 import com.google.common.math.Stats;
 import com.google.common.math.StatsAccumulator;
diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/StatsKeyFactory.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/StatsKeyFactory.java
similarity index 86%
rename from theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/StatsKeyFactory.java
rename to theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/StatsKeyFactory.java
index fdebccaa2d116253c41492cab3443057adef7b36..23ffed974c25e3ef43a49b2a72491d2be7f78d05 100644
--- a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/StatsKeyFactory.java
+++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/StatsKeyFactory.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.application.util;
+package rocks.theodolite.benchmarks.uc3.flink.util;
 
 import java.time.LocalDateTime;
 
diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/StatsRecordFactory.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/StatsRecordFactory.java
similarity index 93%
rename from theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/StatsRecordFactory.java
rename to theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/StatsRecordFactory.java
index 31935df9db0949b05e602109b3edc23dee9499af..f67187e4bcd87198509fc5a8c107c7ed039a1ae0 100644
--- a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/StatsRecordFactory.java
+++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/StatsRecordFactory.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.streamprocessing;
+package rocks.theodolite.benchmarks.uc3.flink.util;
 
 import com.google.common.math.Stats;
 import org.apache.avro.specific.SpecificRecord;
diff --git a/theodolite-benchmarks/uc3-hazelcastjet/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc3-hazelcastjet/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/uc3-hazelcastjet/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc3-hazelcastjet/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc3-hazelcastjet/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc3-hazelcastjet/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc3-hazelcastjet/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc3-hazelcastjet/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc3-hazelcastjet/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc3-hazelcastjet/Dockerfile b/theodolite-benchmarks/uc3-hazelcastjet/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..6dc99aeb7263ef0084e9721ad9bd908a36cd61f6
--- /dev/null
+++ b/theodolite-benchmarks/uc3-hazelcastjet/Dockerfile
@@ -0,0 +1,7 @@
+FROM openjdk:11-slim
+
+ADD build/distributions/uc3-hazelcastjet.tar /
+
+
+CMD  JAVA_OPTS="$JAVA_OPTS -Dorg.slf4j.simpleLogger.defaultLogLevel=$LOG_LEVEL" \
+     /uc3-hazelcastjet/bin/uc3-hazelcastjet
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc3-hazelcastjet/build.gradle b/theodolite-benchmarks/uc3-hazelcastjet/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..737ef6af17cb4c5aa4aa2ee97b5c3e7e4aa0d929
--- /dev/null
+++ b/theodolite-benchmarks/uc3-hazelcastjet/build.gradle
@@ -0,0 +1,5 @@
+plugins {
+  id 'theodolite.hazelcastjet'
+}
+
+mainClassName = "rocks.theodolite.benchmarks.uc3.hazelcastjet.HistoryService"
diff --git a/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/HistoryService.java b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/HistoryService.java
new file mode 100644
index 0000000000000000000000000000000000000000..ecf38bd6c6a85e6d0f1431708a69f3431aff4730
--- /dev/null
+++ b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/HistoryService.java
@@ -0,0 +1,72 @@
+package rocks.theodolite.benchmarks.uc3.hazelcastjet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A microservice that manages the history and, therefore, stores and aggregates incoming
+ * measurements.
+ */
+public class HistoryService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(HistoryService.class);
+
+  // Hazelcast settings (default)
+  private static final String HZ_KUBERNETES_SERVICE_DNS_KEY = "service-dns";
+  private static final String BOOTSTRAP_SERVER_DEFAULT = "localhost:5701";
+
+  // Kafka settings (default)
+  private static final String KAFKA_BOOTSTRAP_DEFAULT = "localhost:9092";
+  private static final String SCHEMA_REGISTRY_URL_DEFAULT = "http://localhost:8081";
+  private static final String KAFKA_INPUT_TOPIC_DEFAULT = "input";
+  private static final String KAFKA_OUTPUT_TOPIC_DEFAULT = "output";
+  
+  // UC3 specific (default)
+  private static final String WINDOW_SIZE_IN_SECONDS_DEFAULT = "2629800";
+  private static final String HOPSIZE_IN_SEC_DEFAULT = "86400";
+
+  // Job name (default)
+  private static final String JOB_NAME = "uc3-hazelcastjet";
+
+  /**
+   * Entrypoint for UC3 using Gradle Run.
+   */
+  public static void main(final String[] args) {
+    final HistoryService uc3HistoryService = new HistoryService();
+    try {
+      uc3HistoryService.run();
+    } catch (final Exception e) { // NOPMD
+      LOGGER.error("ABORT MISSION!: {}", e);
+    }
+  }
+
+  /**
+   * Start a UC3 service.
+   *
+   * @throws Exception This Exception occurs if the Uc3HazelcastJetFactory is used in the wrong way.
+   *         Detailed data is provided once an Exception occurs.
+   */
+  public void run() throws Exception { // NOPMD
+    this.createHazelcastJetApplication();
+  }
+
+  /**
+   * Creates a Hazelcast Jet Application for UC3 using the Uc3HazelcastJetFactory.
+   *
+   * @throws Exception This Exception occurs if the Uc3HazelcastJetFactory is used in the wrong way.
+   *         Detailed data is provided once an Exception occurs.
+   */
+  private void createHazelcastJetApplication() throws Exception { // NOPMD
+    new Uc3HazelcastJetFactory()
+        .setReadPropertiesFromEnv(KAFKA_BOOTSTRAP_DEFAULT, SCHEMA_REGISTRY_URL_DEFAULT, JOB_NAME)
+        .setWritePropertiesFromEnv(KAFKA_BOOTSTRAP_DEFAULT, SCHEMA_REGISTRY_URL_DEFAULT)
+        .setKafkaInputTopicFromEnv(KAFKA_INPUT_TOPIC_DEFAULT)
+        .setKafkaOutputTopicFromEnv(KAFKA_OUTPUT_TOPIC_DEFAULT)
+        .setWindowSizeInSecondsFromEnv(WINDOW_SIZE_IN_SECONDS_DEFAULT)
+        .setHoppingSizeInSecondsFromEnv(HOPSIZE_IN_SEC_DEFAULT)
+        .buildUc3Pipeline()
+        .buildUc3JetInstanceFromEnv(LOGGER, BOOTSTRAP_SERVER_DEFAULT, HZ_KUBERNETES_SERVICE_DNS_KEY)
+        .runUc3Job(JOB_NAME);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3HazelcastJetFactory.java b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3HazelcastJetFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..be6d70d27b9a868914ec5d28e84b4a90454ab56c
--- /dev/null
+++ b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3HazelcastJetFactory.java
@@ -0,0 +1,341 @@
+package rocks.theodolite.benchmarks.uc3.hazelcastjet;
+
+import com.hazelcast.jet.JetInstance;
+import com.hazelcast.jet.config.JobConfig;
+import com.hazelcast.jet.pipeline.Pipeline;
+import io.confluent.kafka.serializers.KafkaAvroDeserializer;
+import java.util.Objects;
+import java.util.Properties;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import org.apache.kafka.common.serialization.StringSerializer;
+import org.slf4j.Logger;
+import rocks.theodolite.benchmarks.commons.hazelcastjet.ConfigurationKeys;
+import rocks.theodolite.benchmarks.commons.hazelcastjet.JetInstanceBuilder;
+import rocks.theodolite.benchmarks.commons.hazelcastjet.KafkaPropertiesBuilder;
+import rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics.HourOfDayKey;
+import rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics.HourOfDayKeySerializer;
+
+/**
+ * A Hazelcast Jet factory which can build a Hazelcast Jet Instance and Pipeline for the UC3
+ * benchmark and lets you start the Hazelcast Jet job. The JetInstance can be built directly as the
+ * Hazelcast Config is managed internally. In order to build the Pipeline, you first have to build
+ * the Read and Write Properties, set the input and output topic, and set the window size in seconds
+ * and the hopping size in seconds. This can be done using internal functions of this factory.
+ * Outside data only refers to custom values or default values in case data of the environment
+ * cannot the fetched.
+ */
+public class Uc3HazelcastJetFactory { // NOPMD
+
+  // Information per History Service
+  private Properties kafkaReadPropsForPipeline;
+  private Properties kafkaWritePropsForPipeline;
+  private String kafkaInputTopic;
+  private String kafkaOutputTopic;
+  private JetInstance uc3JetInstance;
+  private Pipeline uc3JetPipeline;
+  // UC3 specific
+  private int windowSizeInSeconds;
+  private int hoppingSizeInSeconds;
+
+  /////////////////////////////////////
+  // Layer 1 - Hazelcast Jet Run Job //
+  /////////////////////////////////////
+
+  /**
+   * Needs a JetInstance and Pipeline defined in this factors. Adds the pipeline to the existing
+   * JetInstance as a job.
+   *
+   * @param jobName The name of the job.
+   * @throws Exception If either no JetInstance or Pipeline is set, a job cannot be startet.
+   */
+  public void runUc3Job(final String jobName) throws IllegalStateException { // NOPMD
+
+    // Check if a Jet Instance for UC3 is set.
+    if (this.uc3JetInstance == null) {
+      throw new IllegalStateException("Jet Instance is not set! "
+          + "Cannot start a hazelcast jet job for UC3.");
+    }
+
+    // Check if a Pipeline for UC3 is set.
+    if (this.uc3JetPipeline == null) {
+      throw new IllegalStateException(
+          "Hazelcast Pipeline is not set! Cannot start a hazelcast jet job for UC3.");
+    }
+
+    // Adds the job name and joins a job to the JetInstance defined in this factory
+    final JobConfig jobConfig = new JobConfig()
+        .registerSerializer(HourOfDayKey.class, HourOfDayKeySerializer.class)
+        .setName(jobName);
+    this.uc3JetInstance.newJobIfAbsent(this.uc3JetPipeline, jobConfig).join();
+  }
+
+  /////////////
+  // Layer 2 //
+  /////////////
+
+  /**
+   * Build a Hazelcast JetInstance used to run a job on.
+   *
+   * @param logger The logger specified for this JetInstance.
+   * @param bootstrapServerDefault Default bootstrap server in case no value can be derived from the
+   *        environment.
+   * @param hzKubernetesServiceDnsKey The kubernetes service dns key.
+   * @return A Uc3HazelcastJetFactory containing a set JetInstance.
+   */
+  public Uc3HazelcastJetFactory buildUc3JetInstanceFromEnv(final Logger logger,
+      final String bootstrapServerDefault,
+      final String hzKubernetesServiceDnsKey) {
+    this.uc3JetInstance = new JetInstanceBuilder()
+        .setConfigFromEnv(logger, bootstrapServerDefault, hzKubernetesServiceDnsKey)
+        .build();
+    return this;
+  }
+
+  /**
+   * Builds a Hazelcast Jet pipeline used for a JetInstance to run it as a job on. Needs the input
+   * topic and kafka properties defined in this factory beforehand.
+   *
+   * @return A Uc3HazelcastJetFactory containg a set pipeline.
+   * @throws Exception If the input topic or the kafka properties are not defined, the pipeline
+   *         cannot be built.
+   */
+  public Uc3HazelcastJetFactory buildUc3Pipeline() throws IllegalStateException { // NOPMD
+
+    final String defaultPipelineWarning = "Cannot build pipeline."; // NOPMD
+
+    // Check if Properties for the Kafka Input are set.
+    if (this.kafkaReadPropsForPipeline == null) {
+      throw new IllegalStateException("Kafka Read Properties for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if Properties for the Kafka Output are set.
+    if (this.kafkaWritePropsForPipeline == null) {
+      throw new IllegalStateException("Kafka Write Properties for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if the Kafka input topic is set.
+    if (this.kafkaInputTopic == null) {
+      throw new IllegalStateException("Kafka input topic for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if the Kafka output topic is set.
+    if (this.kafkaOutputTopic == null) {
+      throw new IllegalStateException("kafka output topic for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if the window size for the "sliding" window is set.
+    if (this.windowSizeInSeconds <= 0) {
+      throw new IllegalStateException(
+          "window size in seconds for pipeline not set or not greater than 0! "
+              + defaultPipelineWarning);
+    }
+
+    // Check if the hopping distance for the "sliding" window is set.
+    if (this.hoppingSizeInSeconds <= 0) {
+      throw new IllegalStateException(
+          "hopping size in seconds for pipeline not set or not greater than 0! "
+              + defaultPipelineWarning);
+    }
+
+    // Build Pipeline Using the pipelineBuilder
+    final Uc3PipelineBuilder pipeBuilder = new Uc3PipelineBuilder();
+    this.uc3JetPipeline =
+        pipeBuilder.build(this.kafkaReadPropsForPipeline,
+            this.kafkaWritePropsForPipeline,
+            this.kafkaInputTopic, this.kafkaOutputTopic, this.hoppingSizeInSeconds,
+            this.windowSizeInSeconds);
+    // Return Uc3HazelcastJetBuilder factory
+    return this;
+  }
+
+  /////////////
+  // Layer 3 //
+  /////////////
+
+  /**
+   * Sets kafka read properties for pipeline used in this builder.
+   *
+   * @param kafkaReadProperties A propeties object containing necessary values used for the hazelcst
+   *        jet kafka connection to read data.
+   * @return The Uc3HazelcastJetBuilder factory with set kafkaReadPropsForPipeline.
+   */
+  public Uc3HazelcastJetFactory setCustomReadProperties(// NOPMD
+      final Properties kafkaReadProperties) {
+    this.kafkaReadPropsForPipeline = kafkaReadProperties;
+    return this;
+  }
+
+  /**
+   * Sets kafka write properties for pipeline used in this builder.
+   *
+   * @param kafkaWriteProperties A propeties object containing necessary values used for the
+   *        hazelcst jet kafka connection to write data.
+   * @return The Uc3HazelcastJetBuilder factory with set kafkaWritePropsForPipeline.
+   */
+  public Uc3HazelcastJetFactory setCustomWriteProperties(// NOPMD
+      final Properties kafkaWriteProperties) {
+    this.kafkaWritePropsForPipeline = kafkaWriteProperties;
+    return this;
+  }
+
+  /**
+   * Sets kafka read properties for pipeline used in this builder using environment variables.
+   *
+   * @param bootstrapServersDefault Default Bootstrap server in the case that no bootstrap server
+   *        can be fetched from the environment.
+   * @param schemaRegistryUrlDefault Default schema registry url in the case that no schema registry
+   *        url can be fetched from the environment.
+   * @return The Uc3HazelcastJetBuilder factory with set kafkaReadPropertiesForPipeline.
+   */
+  public Uc3HazelcastJetFactory setReadPropertiesFromEnv(// NOPMD
+                                                         final String bootstrapServersDefault,
+                                                         final String schemaRegistryUrlDefault,
+                                                         final String jobName) {
+    // Use KafkaPropertiesBuilder to build a properties object used for kafka
+    final KafkaPropertiesBuilder propsBuilder = new KafkaPropertiesBuilder();
+    final Properties kafkaReadProps =
+        propsBuilder.buildKafkaInputReadPropsFromEnv(bootstrapServersDefault,
+            schemaRegistryUrlDefault,
+            jobName,
+            StringDeserializer.class.getCanonicalName(),
+            KafkaAvroDeserializer.class.getCanonicalName());
+    this.kafkaReadPropsForPipeline = kafkaReadProps;
+    return this;
+  }
+
+  /**
+   * Sets kafka write properties for pipeline used in this builder using environment variables.
+   *
+   * @param bootstrapServersDefault Default Bootstrap server in the case that no bootstrap server
+   *        can be fetched from the environment.
+   * @return The Uc3HazelcastJetBuilder factory with set kafkaWritePropertiesForPipeline.
+   */
+  public Uc3HazelcastJetFactory setWritePropertiesFromEnv(// NOPMD
+      final String bootstrapServersDefault, final String schemaRegistryUrlDefault) {
+    // Use KafkaPropertiesBuilder to build a properties object used for kafka
+    final KafkaPropertiesBuilder propsBuilder = new KafkaPropertiesBuilder();
+    final Properties kafkaWriteProps =
+        propsBuilder.buildKafkaWritePropsFromEnv(bootstrapServersDefault,
+            schemaRegistryUrlDefault,
+            StringSerializer.class.getCanonicalName(),
+            StringSerializer.class.getCanonicalName());
+    this.kafkaWritePropsForPipeline = kafkaWriteProps;
+    return this;
+  }
+
+  /**
+   * Sets the kafka input topic for the pipeline used in this builder.
+   *
+   * @param inputTopic The kafka topic used as the pipeline input.
+   * @return A Uc3HazelcastJetBuilder factory with a set kafkaInputTopic.
+   */
+  public Uc3HazelcastJetFactory setCustomKafkaInputTopic(// NOPMD
+      final String inputTopic) {
+    this.kafkaInputTopic = inputTopic;
+    return this;
+  }
+
+  /**
+   * Sets the kafka input output for the pipeline used in this builder.
+   *
+   * @param outputTopic The kafka topic used as the pipeline output.
+   * @return A Uc3HazelcastJetBuilder factory with a set kafkaOutputTopic.
+   */
+  public Uc3HazelcastJetFactory setCustomKafkaOutputTopic(final String outputTopic) { // NOPMD
+    this.kafkaOutputTopic = outputTopic;
+    return this;
+  }
+
+
+  /**
+   * Sets the kafka input topic for the pipeline used in this builder using environment variables.
+   *
+   * @param defaultInputTopic The default kafka input topic used if no topic is specified by the
+   *        environment.
+   * @return A Uc3HazelcastJetBuilder factory with a set kafkaInputTopic.
+   */
+  public Uc3HazelcastJetFactory setKafkaInputTopicFromEnv(// NOPMD
+      final String defaultInputTopic) {
+    this.kafkaInputTopic = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_INPUT_TOPIC),
+        defaultInputTopic);
+    return this;
+  }
+
+  /**
+   * Sets the kafka output topic for the pipeline used in this builder using environment variables.
+   *
+   * @param defaultOutputTopic The default kafka output topic used if no topic is specified by the
+   *        environment.
+   * @return A Uc3HazelcastJetBuilder factory with a set kafkaOutputTopic.
+   */
+  public Uc3HazelcastJetFactory setKafkaOutputTopicFromEnv(// NOPMD
+      final String defaultOutputTopic) {
+    this.kafkaOutputTopic = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_OUTPUT_TOPIC),
+        defaultOutputTopic);
+    return this;
+  }
+
+  /**
+   * Sets the window size in seconds for the pipeline used in this builder.
+   *
+   * @param windowSizeInSeconds the windowSizeInSeconds to be used for this pipeline.
+   * @return A Uc3HazelcastJetFactory with a set windowSizeInSeconds.
+   */
+  public Uc3HazelcastJetFactory setCustomWindowSizeInSeconds(// NOPMD
+      final int windowSizeInSeconds) {
+    this.windowSizeInSeconds = windowSizeInSeconds;
+    return this;
+  }
+
+  /**
+   * Sets the window size in seconds for the pipeline used in this builder from the environment.
+   *
+   * @param defaultWindowSizeInSeconds the default window size in seconds to be used for this
+   *        pipeline when none is set in the environment.
+   * @return A Uc3HazelcastJetFactory with a set windowSizeInSeconds.
+   */
+  public Uc3HazelcastJetFactory setWindowSizeInSecondsFromEnv(// NOPMD
+      final String defaultWindowSizeInSeconds) {
+    final String windowSizeInSeconds = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.WINDOW_SIZE_IN_SECONDS),
+        defaultWindowSizeInSeconds);
+    final int windowSizeInSecondsNumber = Integer.parseInt(windowSizeInSeconds);
+    this.windowSizeInSeconds = windowSizeInSecondsNumber;
+    return this;
+  }
+
+  /**
+   * Sets the hopping size in seconds for the pipeline used in this builder.
+   *
+   * @param hoppingSizeInSeconds the hoppingSizeInSeconds to be used for this pipeline.
+   * @return A Uc3HazelcastJetFactory with a set hoppingSizeInSeconds.
+   */
+  public Uc3HazelcastJetFactory setCustomHoppingSizeInSeconds(// NOPMD
+      final int hoppingSizeInSeconds) {
+    this.hoppingSizeInSeconds = hoppingSizeInSeconds;
+    return this;
+  }
+
+  /**
+   * Sets the hopping size in seconds for the pipeline used in this builder from the environment.
+   *
+   * @param defaultHoppingSizeInSeconds the default hopping size in seconds to be used for this
+   *        pipeline when none is set in the environment.
+   * @return A Uc3HazelcastJetFactory with a set hoppingSizeInSeconds.
+   */
+  public Uc3HazelcastJetFactory setHoppingSizeInSecondsFromEnv(// NOPMD
+      final String defaultHoppingSizeInSeconds) {
+    final String hoppingSizeInSeconds = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.HOPPING_SIZE_IN_SECONDS),
+        defaultHoppingSizeInSeconds);
+    final int hoppingSizeInSecondsNumber = Integer.parseInt(hoppingSizeInSeconds);
+    this.hoppingSizeInSeconds = hoppingSizeInSecondsNumber;
+    return this;
+  }
+}
diff --git a/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3PipelineBuilder.java b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3PipelineBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8427de60742c2923d4ec17703592f5b8310de0c
--- /dev/null
+++ b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3PipelineBuilder.java
@@ -0,0 +1,125 @@
+package rocks.theodolite.benchmarks.uc3.hazelcastjet;
+
+import com.hazelcast.jet.aggregate.AggregateOperations;
+import com.hazelcast.jet.kafka.KafkaSinks;
+import com.hazelcast.jet.kafka.KafkaSources;
+import com.hazelcast.jet.pipeline.Pipeline;
+import com.hazelcast.jet.pipeline.Sinks;
+import com.hazelcast.jet.pipeline.StreamSource;
+import com.hazelcast.jet.pipeline.StreamStage;
+import com.hazelcast.jet.pipeline.WindowDefinition;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.TimeZone;
+import java.util.concurrent.TimeUnit;
+import rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics.HourOfDayKey;
+import rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics.HoursOfDayKeyFactory;
+import rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics.StatsKeyFactory;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * Builder to build a HazelcastJet Pipeline for UC3 which can be used for stream processing using
+ * Hazelcast Jet.
+ */
+public class Uc3PipelineBuilder {
+
+  /**
+   * Builds a pipeline which can be used for stream processing using Hazelcast Jet.
+   *
+   * @param kafkaReadPropsForPipeline Properties Object containing the necessary kafka reads
+   *        attributes.
+   * @param kafkaWritePropsForPipeline Properties Object containing the necessary kafka write
+   *        attributes.
+   * @param kafkaInputTopic The name of the input topic used for the pipeline.
+   * @param kafkaOutputTopic The name of the output topic used for the pipeline.
+   * @param hoppingSizeInSeconds The hop length of the sliding window used in the aggregation of
+   *        this pipeline.
+   * @param windowSizeInSeconds The window length of the sliding window used in the aggregation of
+   *        this pipeline.
+   * @return returns a Pipeline used which can be used in a Hazelcast Jet Instance to process data
+   *         for UC3.
+   */
+  public Pipeline build(final Properties kafkaReadPropsForPipeline,
+      final Properties kafkaWritePropsForPipeline, final String kafkaInputTopic,
+      final String kafkaOutputTopic,
+      final int hoppingSizeInSeconds, final int windowSizeInSeconds) {
+
+    // Define a new Pipeline
+    final Pipeline pipe = Pipeline.create();
+
+    // Define the source
+    final StreamSource<Entry<String, ActivePowerRecord>> kafkaSource = KafkaSources
+        .<String, ActivePowerRecord>kafka(
+            kafkaReadPropsForPipeline, kafkaInputTopic);
+
+    // Extend topology for UC3
+    final StreamStage<Map.Entry<String, String>> uc3Product =
+        this.extendUc3Topology(pipe, kafkaSource, hoppingSizeInSeconds, windowSizeInSeconds);
+
+    // Add Sink1: Logger
+    uc3Product.writeTo(Sinks.logger());
+    // Add Sink2: Write back to kafka for the final benchmark
+    uc3Product.writeTo(KafkaSinks.<String, String>kafka(
+        kafkaWritePropsForPipeline, kafkaOutputTopic));
+
+    return pipe;
+  }
+
+  /**
+   * Extends to a blank Hazelcast Jet Pipeline the UC3 topology defined by theodolite.
+   *
+   * <p>
+   * UC3 takes {@code ActivePowerRecord} object, groups them by keys and calculates average double
+   * values for a sliding window and sorts them into the hour of the day.
+   * </p>
+   *
+   * @param pipe The blank hazelcast jet pipeline to extend the logic to.
+   * @param source A streaming source to fetch data from.
+   * @param hoppingSizeInSeconds The jump distance of the "sliding" window.
+   * @param windowSizeInSeconds The size of the "sliding" window.
+   * @return A {@code StreamStage<Map.Entry<String,String>>} with the above definition of the key
+   *         and value of the Entry object. It can be used to be further modified or directly be
+   *         written into a sink.
+   */
+  public StreamStage<Map.Entry<String, String>> extendUc3Topology(final Pipeline pipe,
+      final StreamSource<Entry<String, ActivePowerRecord>> source, final int hoppingSizeInSeconds,
+      final int windowSizeInSeconds) {
+    // Build the pipeline topology.
+    return pipe
+        .readFrom(source)
+        // use Timestamps
+        .withNativeTimestamps(0)
+        .setLocalParallelism(1)
+        // Map timestamp to hour of day and create new key using sensorID and
+        // datetime mapped to HourOfDay
+        .map(record -> {
+          final String sensorId = record.getValue().getIdentifier();
+          final long timestamp = record.getValue().getTimestamp();
+          final LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp),
+              TimeZone.getDefault().toZoneId());
+
+          final StatsKeyFactory<HourOfDayKey> keyFactory = new HoursOfDayKeyFactory();
+          final HourOfDayKey newKey = keyFactory.createKey(sensorId, dateTime);
+
+          return Map.entry(newKey, record.getValue());
+        })
+        // group by new keys
+        .groupingKey(Entry::getKey)
+        // Sliding/Hopping Window
+        .window(WindowDefinition.sliding(TimeUnit.SECONDS.toMillis(windowSizeInSeconds),
+            TimeUnit.SECONDS.toMillis(hoppingSizeInSeconds)))
+        // get average value of group (sensoreId,hourOfDay)
+        .aggregate(
+            AggregateOperations.averagingDouble(record -> record.getValue().getValueInW()))
+        // map to return pair (sensorID,hourOfDay) -> (averaged what value)
+        .map(agg -> {
+          final String theValue = agg.getValue().toString();
+          final String theKey = agg.getKey().toString();
+          return Map.entry(theKey, theValue);
+        });
+  }
+
+}
diff --git a/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/uc3specifics/HourOfDayKey.java b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/uc3specifics/HourOfDayKey.java
new file mode 100644
index 0000000000000000000000000000000000000000..c69f433f3af7ec0484c254af9e59e7d284379cb0
--- /dev/null
+++ b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/uc3specifics/HourOfDayKey.java
@@ -0,0 +1,50 @@
+package rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics;
+
+import java.util.Objects;
+
+/**
+ * A key consisting of a hour of a day and a sensorID.
+ *
+ */
+public class HourOfDayKey {
+
+  private final int hourOfDay;
+  private final String sensorId;
+
+  public HourOfDayKey(final int hourOfDay, final String sensorId) {
+    this.hourOfDay = hourOfDay;
+    this.sensorId = sensorId;
+  }
+
+  public int getHourOfDay() {
+    return this.hourOfDay;
+  }
+
+  public String getSensorId() {
+    return this.sensorId;
+  }
+
+  @Override
+  public String toString() {
+    return this.sensorId + ";" + this.hourOfDay;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(this.hourOfDay, this.sensorId);
+  }
+
+  @Override
+  public boolean equals(final Object obj) {
+    if (obj == this) {
+      return true;
+    }
+    if (obj instanceof HourOfDayKey) {
+      final HourOfDayKey other = (HourOfDayKey) obj;
+      return Objects.equals(this.hourOfDay, other.hourOfDay)
+          && Objects.equals(this.sensorId, other.sensorId);
+    }
+    return false;
+  }
+
+}
diff --git a/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/uc3specifics/HourOfDayKeySerializer.java b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/uc3specifics/HourOfDayKeySerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..91ba3f2be26f4317a1dec81caf9080da8c1edc9c
--- /dev/null
+++ b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/uc3specifics/HourOfDayKeySerializer.java
@@ -0,0 +1,32 @@
+package rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics;
+
+import com.hazelcast.nio.ObjectDataInput;
+import com.hazelcast.nio.ObjectDataOutput;
+import com.hazelcast.nio.serialization.StreamSerializer;
+import java.io.IOException;
+
+/**
+ * A pipeline serializer for the HourOfDayKey to allow for parallelization.
+ * 
+ */
+public class HourOfDayKeySerializer implements StreamSerializer<HourOfDayKey> {
+
+  private static final int TYPE_ID = 1;
+
+  @Override
+  public int getTypeId() {
+    return TYPE_ID;
+  }
+
+  @Override
+  public void write(final ObjectDataOutput out, final HourOfDayKey key) throws IOException {
+    out.writeInt(key.getHourOfDay());
+    out.writeString(key.getSensorId());
+  }
+
+  @Override
+  public HourOfDayKey read(final ObjectDataInput in) throws IOException {
+    return new HourOfDayKey(in.readInt(), in.readString());
+  }
+
+}
diff --git a/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/uc3specifics/HoursOfDayKeyFactory.java b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/uc3specifics/HoursOfDayKeyFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..4eddb85efebf5b8b07317d0cd39f36b90d3f4fcd
--- /dev/null
+++ b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/uc3specifics/HoursOfDayKeyFactory.java
@@ -0,0 +1,22 @@
+package rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics;
+
+import java.time.LocalDateTime;
+
+/**
+ * A factory class to build an {@link HourOfDayKey}.
+ *
+ */
+public class HoursOfDayKeyFactory implements StatsKeyFactory<HourOfDayKey> {
+
+  @Override
+  public HourOfDayKey createKey(final String sensorId, final LocalDateTime dateTime) {
+    final int hourOfDay = dateTime.getHour();
+    return new HourOfDayKey(hourOfDay, sensorId);
+  }
+
+  @Override
+  public String getSensorId(final HourOfDayKey key) {
+    return key.getSensorId();
+  }
+
+}
diff --git a/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/uc3specifics/StatsKeyFactory.java b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/uc3specifics/StatsKeyFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..2a404781e5916473604f14f87b9c3eccf9eda342
--- /dev/null
+++ b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/uc3specifics/StatsKeyFactory.java
@@ -0,0 +1,17 @@
+package rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics;
+
+import java.time.LocalDateTime;
+
+/**
+ * Factory interface for creating a stats key from a sensor id and a {@link LocalDateTime} object
+ * and vice versa.
+ *
+ * @param <T> Type of the key
+ */
+public interface StatsKeyFactory<T> {
+
+  T createKey(String sensorId, LocalDateTime dateTime);
+
+  String getSensorId(T key);
+
+}
diff --git a/theodolite-benchmarks/uc3-hazelcastjet/src/main/resources/META-INF/application.properties b/theodolite-benchmarks/uc3-hazelcastjet/src/main/resources/META-INF/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..e3371cc87e20e85e6e8c327955537e6e49dab86e
--- /dev/null
+++ b/theodolite-benchmarks/uc3-hazelcastjet/src/main/resources/META-INF/application.properties
@@ -0,0 +1,8 @@
+application.name=theodolite-uc1-application
+application.version=0.0.1
+
+kafka.bootstrap.servers=localhost:9092
+kafka.input.topic=input
+
+schema.registry.url=http://localhost:8081
+
diff --git a/theodolite-benchmarks/uc3-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3PipelineTest.java b/theodolite-benchmarks/uc3-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3PipelineTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..3df4f4642f1bc6c8637f90bcae3f352f5c298e51
--- /dev/null
+++ b/theodolite-benchmarks/uc3-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3PipelineTest.java
@@ -0,0 +1,162 @@
+package rocks.theodolite.benchmarks.uc3.hazelcastjet;
+
+import com.hazelcast.jet.Jet;
+import com.hazelcast.jet.JetInstance;
+import com.hazelcast.jet.config.JetConfig;
+import com.hazelcast.jet.config.JobConfig;
+import com.hazelcast.jet.core.JetTestSupport;
+import com.hazelcast.jet.pipeline.Pipeline;
+import com.hazelcast.jet.pipeline.StreamSource;
+import com.hazelcast.jet.pipeline.StreamStage;
+import com.hazelcast.jet.pipeline.test.AssertionCompletedException;
+import com.hazelcast.jet.pipeline.test.Assertions;
+import com.hazelcast.jet.pipeline.test.TestSources;
+import com.hazelcast.jet.test.SerialTest;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.Map.Entry;
+import java.util.concurrent.CompletionException;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import rocks.theodolite.benchmarks.uc3.hazelcastjet.Uc3PipelineBuilder;
+import rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics.HourOfDayKey;
+import rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics.HourOfDayKeySerializer;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * Test methods for the Hazelcast Jet Implementation of UC3.
+ */
+@Category(SerialTest.class)
+public class Uc3PipelineTest extends JetTestSupport {
+
+  // Test Machinery
+  private JetInstance testInstance = null;
+  private Pipeline testPipeline = null;
+  private StreamStage<Entry<String, String>> uc3Topology = null;
+
+
+  /**
+   * Creates the JetInstance, defines a new Hazelcast Jet Pipeline and extends the UC3 topology.
+   * Allows for quick extension of tests.
+   */
+  @Before
+  public void buildUc3Pipeline() {
+
+    // Setup Configuration
+    int testItemsPerSecond = 1;
+    String testSensorName = "TEST-SENSOR";
+    Double testValueInW = 10.0;
+    int testHopSizeInSec = 1;
+    int testWindowSizeInSec = 50;
+    // Used to check hourOfDay
+    long mockTimestamp = 1632741651;
+
+
+    // Create mock jet instance with configuration
+    final String testClusterName = randomName();
+    final JetConfig testJetConfig = new JetConfig();
+    testJetConfig.getHazelcastConfig().setClusterName(testClusterName);
+    this.testInstance = this.createJetMember(testJetConfig);
+
+    // Create a test source
+    final StreamSource<Entry<String, ActivePowerRecord>> testSource =
+        TestSources.itemStream(testItemsPerSecond, (timestamp, item) -> {
+          final ActivePowerRecord testRecord =
+              new ActivePowerRecord(testSensorName, mockTimestamp, testValueInW);
+          final Entry<String, ActivePowerRecord> testEntry =
+              Map.entry(testSensorName, testRecord);
+          return testEntry;
+        });
+
+    // Create pipeline to test
+    Uc3PipelineBuilder pipelineBuilder = new Uc3PipelineBuilder();
+    this.testPipeline = Pipeline.create();
+    this.uc3Topology = pipelineBuilder.extendUc3Topology(testPipeline, testSource,
+        testHopSizeInSec, testWindowSizeInSec);
+  }
+
+  /**
+   * Tests if no items reach the end before the first window ends.
+   */
+  @Test
+  public void testOutput() {
+
+    // Assertion Configuration
+    int timeout = 10;
+    String testSensorName = "TEST-SENSOR";
+    Double testValueInW = 10.0;
+    // Used to check hourOfDay
+    long mockTimestamp = 1632741651;
+
+    // Assertion
+    this.uc3Topology.apply(Assertions.assertCollectedEventually(timeout,
+        collection -> {
+
+          // DEBUG
+          System.out.println("DEBUG: CHECK 1 || Entered Assertion of testOutput()");
+
+          // Check all collected Items
+          boolean allOkay = true;
+          if (collection != null) {
+            System.out.println("DEBUG: CHECK 2 || Collection Size: " + collection.size());
+            for (int i = 0; i < collection.size(); i++) {
+
+              // Build hour of day
+              long timestamp = mockTimestamp;
+              int expectedHour = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp),
+                  TimeZone.getDefault().toZoneId()).getHour();
+
+              // Compare expected output with generated output
+              Entry<String, String> currentEntry = collection.get(i);
+              String expectedKey = testSensorName + ";" + expectedHour;
+              String expectedValue = testValueInW.toString();
+
+              // DEBUG
+              System.out.println(
+                  "DEBUG: CHECK 3 || Expected Output: '" + expectedKey + "=" + expectedValue
+                      + "' - Actual Output: '" + currentEntry.getKey() + "="
+                      + currentEntry.getValue().toString() + "'");
+
+              if (!(currentEntry.getKey().equals(expectedKey)
+                  && currentEntry.getValue().toString().equals(expectedValue))) {
+                System.out.println("DEBUG: CHECK 5 || Failed assertion!");
+                allOkay = false;
+              }
+            }
+          }
+
+          // Assertion
+          Assert.assertTrue(
+              "Items do not match expected structure!", allOkay);
+        }));
+
+    // Run the test!
+    try {
+      final JobConfig jobConfig = new JobConfig()
+          .registerSerializer(HourOfDayKey.class, HourOfDayKeySerializer.class);
+      this.testInstance.newJob(this.testPipeline, jobConfig).join();
+      Assert.fail("Job should have completed with an AssertionCompletedException, "
+          + "but completed normally!");
+    } catch (final CompletionException e) {
+      final String errorMsg = e.getCause().getMessage();
+      Assert.assertTrue(
+          "Job was expected to complete with AssertionCompletedException, but completed with: "
+              + e.getCause(),
+          errorMsg.contains(AssertionCompletedException.class.getName()));
+    }
+
+  }
+
+  @After
+  public void after() {
+    // Shuts down all running Jet Instances
+    Jet.shutdownAll();
+  }
+
+}
diff --git a/theodolite-benchmarks/uc3-kstreams/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc3-kstreams/.settings/org.eclipse.jdt.ui.prefs
index fa98ca63d77bdee891150bd6713f70197a75cefc..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc3-kstreams/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc3-kstreams/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,25 +12,72 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
 cleanup.remove_redundant_semicolons=true
@@ -37,6 +85,7 @@ cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,27 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -79,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -114,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc3-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc3-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/uc3-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/uc3-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/uc3-kstreams/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc3-kstreams/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/uc3-kstreams/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/uc3-kstreams/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc3-kstreams/build.gradle b/theodolite-benchmarks/uc3-kstreams/build.gradle
index d588d85ae88e3efd2b687e44e9eb9561a45cd8c0..ee92f636476cc5ee12f32c5e3f78d5a71c298a29 100644
--- a/theodolite-benchmarks/uc3-kstreams/build.gradle
+++ b/theodolite-benchmarks/uc3-kstreams/build.gradle
@@ -2,4 +2,4 @@ plugins {
   id 'theodolite.kstreams'
 }
 
-mainClassName = "theodolite.uc3.application.HistoryService"
+mainClassName = "rocks.theodolite.benchmarks.uc3.kstreams.HistoryService"
diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/application/HistoryService.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HistoryService.java
similarity index 91%
rename from theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/application/HistoryService.java
rename to theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HistoryService.java
index 84fb29969d2ce37a1d443752790379b1af634df5..a327d2ecfa4c0727e7a29a69e7ab8910afdfd3d2 100644
--- a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/application/HistoryService.java
+++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HistoryService.java
@@ -1,11 +1,10 @@
-package theodolite.uc3.application;
+package rocks.theodolite.benchmarks.uc3.kstreams;
 
 import java.time.Duration;
 import java.util.concurrent.CompletableFuture;
 import org.apache.commons.configuration2.Configuration;
 import org.apache.kafka.streams.KafkaStreams;
-import theodolite.commons.kafkastreams.ConfigurationKeys;
-import theodolite.uc3.streamprocessing.Uc3KafkaStreamsBuilder;
+import rocks.theodolite.benchmarks.commons.kstreams.ConfigurationKeys;
 import titan.ccp.common.configuration.ServiceConfigurations;
 
 /**
diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/HourOfDayKey.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayKey.java
similarity index 95%
rename from theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/HourOfDayKey.java
rename to theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayKey.java
index 549674f9f546a26d38491195edc2139aeadd785b..4e4d97986662f4777fc6ff8dafc28860ed49dc85 100644
--- a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/HourOfDayKey.java
+++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayKey.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.streamprocessing;
+package rocks.theodolite.benchmarks.uc3.kstreams;
 
 import java.util.Objects;
 
diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/HourOfDayKeyFactory.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayKeyFactory.java
similarity index 90%
rename from theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/HourOfDayKeyFactory.java
rename to theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayKeyFactory.java
index 837ca9d32e1a353917adcd3f70eb1af51d801613..02fdbaf56d0f2d1e3e317ecc3cd17710f8a3ea5c 100644
--- a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/HourOfDayKeyFactory.java
+++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayKeyFactory.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.streamprocessing;
+package rocks.theodolite.benchmarks.uc3.kstreams;
 
 import java.time.LocalDateTime;
 
diff --git a/theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDayKeySerde.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayKeySerde.java
similarity index 95%
rename from theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDayKeySerde.java
rename to theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayKeySerde.java
index a0f8e0bbaf959154bfbab69d83da56c81d55802a..4014e5e30dee36a737ab582e527fc8fb4b8a32a9 100644
--- a/theodolite-benchmarks/uc3-beam/src/main/java/application/HourOfDayKeySerde.java
+++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayKeySerde.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc3.kstreams;
 
 import org.apache.kafka.common.serialization.Serde;
 import titan.ccp.common.kafka.simpleserdes.BufferSerde;
diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/HourOfDayRecordFactory.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayRecordFactory.java
similarity index 94%
rename from theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/HourOfDayRecordFactory.java
rename to theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayRecordFactory.java
index d8a42b74e5ca1cc55f9f21de62a5d8f877223e62..3d67a6ebe86eb33378fe0711b6b8ca1ab1f5c6a9 100644
--- a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/HourOfDayRecordFactory.java
+++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayRecordFactory.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.application.util;
+package rocks.theodolite.benchmarks.uc3.kstreams;
 
 import com.google.common.math.Stats;
 import org.apache.kafka.streams.kstream.Windowed;
diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/RecordDatabaseAdapter.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/RecordDatabaseAdapter.java
similarity index 98%
rename from theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/RecordDatabaseAdapter.java
rename to theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/RecordDatabaseAdapter.java
index 342cb3e04cd632fc4e8129de0bad6f12e8119dfa..111e262289ba25b6a41c65d0144119342efa2c52 100644
--- a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/RecordDatabaseAdapter.java
+++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/RecordDatabaseAdapter.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.streamprocessing;
+package rocks.theodolite.benchmarks.uc3.kstreams;
 
 import java.util.Collection;
 import java.util.List;
diff --git a/theodolite-benchmarks/uc3-beam/src/main/java/application/StatsKeyFactory.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/StatsKeyFactory.java
similarity index 86%
rename from theodolite-benchmarks/uc3-beam/src/main/java/application/StatsKeyFactory.java
rename to theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/StatsKeyFactory.java
index 820168058f88ca21f8efcf61c7ebed60c08aa200..2473665a35fc0bda13bcbd462bfa98c0ebc00d9b 100644
--- a/theodolite-benchmarks/uc3-beam/src/main/java/application/StatsKeyFactory.java
+++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/StatsKeyFactory.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc3.kstreams;
 
 import java.time.LocalDateTime;
 
diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/StatsRecordFactory.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/StatsRecordFactory.java
similarity index 93%
rename from theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/StatsRecordFactory.java
rename to theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/StatsRecordFactory.java
index 61333c99966b1ffea608d225f17d8460eac9ada1..1cbf031bde6744f1013220998241c4896fda504b 100644
--- a/theodolite-benchmarks/uc3-flink/src/main/java/theodolite/uc3/application/util/StatsRecordFactory.java
+++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/StatsRecordFactory.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.application.util;
+package rocks.theodolite.benchmarks.uc3.kstreams;
 
 import com.google.common.math.Stats;
 import org.apache.avro.specific.SpecificRecord;
diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/TopologyBuilder.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/TopologyBuilder.java
similarity index 87%
rename from theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/TopologyBuilder.java
rename to theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/TopologyBuilder.java
index 1e976c07158720b3681d89413a5f277b1395f32d..b956959c5680c3c23eb35c0548004bb55de09a20 100644
--- a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/TopologyBuilder.java
+++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/TopologyBuilder.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.streamprocessing;
+package rocks.theodolite.benchmarks.uc3.kstreams;
 
 import com.google.common.math.Stats;
 import java.time.Duration;
@@ -16,7 +16,7 @@ import org.apache.kafka.streams.kstream.Grouped;
 import org.apache.kafka.streams.kstream.Materialized;
 import org.apache.kafka.streams.kstream.Produced;
 import org.apache.kafka.streams.kstream.TimeWindows;
-import theodolite.uc3.streamprocessing.util.StatsFactory;
+import rocks.theodolite.benchmarks.uc3.kstreams.util.StatsFactory;
 import titan.ccp.common.kafka.GenericSerde;
 import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory;
 import titan.ccp.model.records.ActivePowerRecord;
@@ -60,17 +60,18 @@ public class TopologyBuilder {
     final Serde<HourOfDayKey> keySerde = HourOfDayKeySerde.create();
 
     this.builder
-        .stream(this.inputTopic,
-            Consumed.with(Serdes.String(),
-                this.srAvroSerdeFactory.<ActivePowerRecord>forValues()))
+        .stream(this.inputTopic, Consumed.with(
+            Serdes.String(),
+            this.srAvroSerdeFactory.<ActivePowerRecord>forValues()))
         .selectKey((key, value) -> {
           final Instant instant = Instant.ofEpochMilli(value.getTimestamp());
           final LocalDateTime dateTime = LocalDateTime.ofInstant(instant, this.zone);
           return keyFactory.createKey(value.getIdentifier(), dateTime);
         })
-        .groupByKey(
-            Grouped.with(keySerde, this.srAvroSerdeFactory.forValues()))
-        .windowedBy(TimeWindows.of(this.aggregtionDuration).advanceBy(this.aggregationAdvance))
+        .groupByKey(Grouped.with(keySerde, this.srAvroSerdeFactory.forValues()))
+        .windowedBy(TimeWindows
+            .ofSizeWithNoGrace(this.aggregtionDuration)
+            .advanceBy(this.aggregationAdvance))
         .aggregate(
             () -> Stats.of(),
             (k, record, stats) -> StatsFactory.accumulate(stats, record.getValueInW()),
diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/Uc3KafkaStreamsBuilder.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/Uc3KafkaStreamsBuilder.java
similarity index 93%
rename from theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/Uc3KafkaStreamsBuilder.java
rename to theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/Uc3KafkaStreamsBuilder.java
index ea9b064602b1aa7cf7350826da18990ae3191d43..3c80e5eedef0c9dda8ac3c729f158d0872b5769b 100644
--- a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/Uc3KafkaStreamsBuilder.java
+++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/Uc3KafkaStreamsBuilder.java
@@ -1,11 +1,11 @@
-package theodolite.uc3.streamprocessing;
+package rocks.theodolite.benchmarks.uc3.kstreams;
 
 import java.time.Duration;
 import java.util.Objects;
 import java.util.Properties;
 import org.apache.commons.configuration2.Configuration;
 import org.apache.kafka.streams.Topology;
-import theodolite.commons.kafkastreams.KafkaStreamsBuilder;
+import rocks.theodolite.benchmarks.commons.kstreams.KafkaStreamsBuilder;
 import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory;
 
 /**
diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/util/StatsFactory.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/util/StatsFactory.java
similarity index 90%
rename from theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/util/StatsFactory.java
rename to theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/util/StatsFactory.java
index 8099c85d652e57d30fe38e9d598783e2dc45ecb9..f2017073fbf3e240b5952f3f729f97e5ab5d1be5 100644
--- a/theodolite-benchmarks/uc3-kstreams/src/main/java/theodolite/uc3/streamprocessing/util/StatsFactory.java
+++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/util/StatsFactory.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.streamprocessing.util;
+package rocks.theodolite.benchmarks.uc3.kstreams.util;
 
 import com.google.common.math.Stats;
 import com.google.common.math.StatsAccumulator;
diff --git a/theodolite-benchmarks/uc3-load-generator/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc3-load-generator/.settings/org.eclipse.jdt.ui.prefs
index fa98ca63d77bdee891150bd6713f70197a75cefc..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc3-load-generator/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc3-load-generator/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,25 +12,72 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
 cleanup.remove_redundant_semicolons=true
@@ -37,6 +85,7 @@ cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,27 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -79,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -114,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc3-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc3-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/uc3-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/uc3-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/uc3-load-generator/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc3-load-generator/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/uc3-load-generator/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/uc3-load-generator/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc3-load-generator/build.gradle b/theodolite-benchmarks/uc3-load-generator/build.gradle
index fddc53ae8273a44d178e8828a38a503196af9208..b78846dd6ab4aee98755fd582acb2648a7319cd6 100644
--- a/theodolite-benchmarks/uc3-load-generator/build.gradle
+++ b/theodolite-benchmarks/uc3-load-generator/build.gradle
@@ -2,4 +2,4 @@ plugins {
   id 'theodolite.load-generator'
 }
 
-mainClassName = "theodolite.uc3.workloadgenerator.LoadGenerator"
+mainClassName = "rocks.theodolite.benchmarks.uc3.loadgenerator.LoadGenerator"
diff --git a/theodolite-benchmarks/uc3-load-generator/src/main/java/theodolite/uc3/workloadgenerator/LoadGenerator.java b/theodolite-benchmarks/uc3-load-generator/src/main/java/rocks/theodolite/benchmarks/uc3/loadgenerator/LoadGenerator.java
similarity index 75%
rename from theodolite-benchmarks/uc3-load-generator/src/main/java/theodolite/uc3/workloadgenerator/LoadGenerator.java
rename to theodolite-benchmarks/uc3-load-generator/src/main/java/rocks/theodolite/benchmarks/uc3/loadgenerator/LoadGenerator.java
index 97527abfdd86f5ea39c20c3da31cd7cd26b674e5..cac88e54a8a6d811946e3e021576f1049561b344 100644
--- a/theodolite-benchmarks/uc3-load-generator/src/main/java/theodolite/uc3/workloadgenerator/LoadGenerator.java
+++ b/theodolite-benchmarks/uc3-load-generator/src/main/java/rocks/theodolite/benchmarks/uc3/loadgenerator/LoadGenerator.java
@@ -1,4 +1,4 @@
-package theodolite.uc3.workloadgenerator;
+package rocks.theodolite.benchmarks.uc3.loadgenerator;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -16,7 +16,7 @@ public final class LoadGenerator {
 
   public static void main(final String[] args) {
     LOGGER.info("Start workload generator for use case UC3");
-    theodolite.commons.workloadgeneration.LoadGenerator.fromEnvironment().run();
+    rocks.theodolite.benchmarks.loadgenerator.LoadGenerator.fromEnvironment().run();
   }
 
 }
diff --git a/theodolite-benchmarks/uc4-beam-flink/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc4-beam-flink/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/uc4-beam-flink/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc4-beam-flink/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc4-beam-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc4-beam-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc4-beam-flink/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc4-beam-flink/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc4-beam-flink/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc4-beam-flink/build.gradle b/theodolite-benchmarks/uc4-beam-flink/build.gradle
index 7ace89a2275e29e22186f7b67dcb7816cc7a85d0..8ccf18a2df2198ebd9749b0af095dffff12bd380 100644
--- a/theodolite-benchmarks/uc4-beam-flink/build.gradle
+++ b/theodolite-benchmarks/uc4-beam-flink/build.gradle
@@ -2,9 +2,18 @@ plugins {
   id 'theodolite.beam.flink'
 }
 
-
 dependencies {
   implementation project(':uc4-beam')
 }
 
-mainClassName = 'application.Uc4BeamFlink'
\ No newline at end of file
+sourceSets {
+  main {
+    resources {
+      srcDirs += [
+        project(':uc4-beam').sourceSets.main.resources
+      ]
+    }
+  }
+}
+
+mainClassName = 'rocks.theodolite.benchmarks.uc4.beam.flink.Uc4BeamFlink'
diff --git a/theodolite-benchmarks/uc4-beam-flink/src/main/java/application/Uc4BeamFlink.java b/theodolite-benchmarks/uc4-beam-flink/src/main/java/application/Uc4BeamFlink.java
deleted file mode 100644
index 90f9a4a292e99526fa94c7dd512bdcec548fbb4f..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc4-beam-flink/src/main/java/application/Uc4BeamFlink.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package application;
-
-import org.apache.beam.runners.flink.FlinkRunner;
-import org.apache.beam.sdk.Pipeline;
-import theodolite.commons.beam.AbstractBeamService;
-
-/**
- * Implementation of the use case Hierarchical Aggregation using Apache Beam with the Flink
- * Runner.
- **/
-public final class Uc4BeamFlink extends AbstractBeamService {
-
-
-  /**
-   * Private constructor setting specific options for this use case.
-   */
-  private Uc4BeamFlink(final String[] args) { //NOPMD
-    super(args);
-    this.options.setRunner(FlinkRunner.class);
-  }
-
-  /**
-   * Start running this microservice.
-   */
-  public static void main(final String[] args) {
-
-    final Uc4BeamFlink uc4BeamFlink = new Uc4BeamFlink(args);
-
-    final Pipeline pipeline = new Uc4BeamPipeline(uc4BeamFlink.options, uc4BeamFlink.getConfig());
-
-    pipeline.run().waitUntilFinish();
-  }
-
-}
diff --git a/theodolite-benchmarks/uc4-beam-flink/src/main/java/rocks/theodolite/benchmarks/uc4/beam/flink/Uc4BeamFlink.java b/theodolite-benchmarks/uc4-beam-flink/src/main/java/rocks/theodolite/benchmarks/uc4/beam/flink/Uc4BeamFlink.java
new file mode 100644
index 0000000000000000000000000000000000000000..f5f9af3fc14b57476975708a139788e7f0386953
--- /dev/null
+++ b/theodolite-benchmarks/uc4-beam-flink/src/main/java/rocks/theodolite/benchmarks/uc4/beam/flink/Uc4BeamFlink.java
@@ -0,0 +1,21 @@
+package rocks.theodolite.benchmarks.uc4.beam.flink;
+
+import org.apache.beam.runners.flink.FlinkRunner;
+import rocks.theodolite.benchmarks.commons.beam.BeamService;
+import rocks.theodolite.benchmarks.uc4.beam.PipelineFactory;
+
+/**
+ * Implementation of the use case Hierarchical Aggregation using Apache Beam with the Flink Runner.
+ **/
+public final class Uc4BeamFlink {
+
+  private Uc4BeamFlink() {}
+
+  /**
+   * Start running this microservice.
+   */
+  public static void main(final String[] args) {
+    new BeamService(PipelineFactory.factory(), FlinkRunner.class, args).runStandalone();
+  }
+
+}
diff --git a/theodolite-benchmarks/uc4-beam-samza/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc4-beam-samza/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/uc4-beam-samza/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc4-beam-samza/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc4-beam-samza/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc4-beam-samza/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc4-beam-samza/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc4-beam-samza/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc4-beam-samza/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc4-beam-samza/Dockerfile b/theodolite-benchmarks/uc4-beam-samza/Dockerfile
index ffb82ee09e99384d4914a0f86b6d9214fc161381..b59585f748b95cf62e59be01c8fa9dc0d919f43a 100644
--- a/theodolite-benchmarks/uc4-beam-samza/Dockerfile
+++ b/theodolite-benchmarks/uc4-beam-samza/Dockerfile
@@ -5,4 +5,4 @@ ENV MAX_SOURCE_PARALLELISM=1024
 ADD build/distributions/uc4-beam-samza.tar /
 ADD samza-standalone.properties /
 
-CMD /uc4-beam-samza/bin/uc4-beam-samza --configFactory=org.apache.samza.config.factories.PropertiesConfigFactory --configFilePath=samza-standalone.properties --samzaExecutionEnvironment=STANDALONE --maxSourceParallelism=$MAX_SOURCE_PARALLELISM --enableMetrics=false --configOverride="{\"job.coordinator.zk.connect\":\"$SAMZA_JOB_COORDINATOR_ZK_CONNECT\"}"
+CMD /uc4-beam-samza/bin/uc4-beam-samza --configFilePath=samza-standalone.properties --samzaExecutionEnvironment=STANDALONE --maxSourceParallelism=$MAX_SOURCE_PARALLELISM --enableMetrics=false --configOverride="{\"job.coordinator.zk.connect\":\"$SAMZA_JOB_COORDINATOR_ZK_CONNECT\"}"
diff --git a/theodolite-benchmarks/uc4-beam-samza/build.gradle b/theodolite-benchmarks/uc4-beam-samza/build.gradle
index 90dcc76b0cae5aeca61f76d0cb73347b2407408b..38e21bfd271587d6ef957d0b8ad0ed32c0ab4940 100644
--- a/theodolite-benchmarks/uc4-beam-samza/build.gradle
+++ b/theodolite-benchmarks/uc4-beam-samza/build.gradle
@@ -6,5 +6,14 @@ dependencies {
   implementation project(':uc4-beam')
 }
 
+sourceSets {
+  main {
+    resources {
+      srcDirs += [
+        project(':uc4-beam').sourceSets.main.resources
+      ]
+    }
+  }
+}
 
-mainClassName = "application.Uc4BeamSamza"
+mainClassName = "rocks.theodolite.benchmarks.uc4.beam.samza.Uc4BeamSamza"
diff --git a/theodolite-benchmarks/uc4-beam-samza/src/main/java/application/Uc4BeamSamza.java b/theodolite-benchmarks/uc4-beam-samza/src/main/java/application/Uc4BeamSamza.java
deleted file mode 100644
index 3894fa95f16253e0a165dde70bf25d4a4bee96cb..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc4-beam-samza/src/main/java/application/Uc4BeamSamza.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package application;
-
-import org.apache.beam.runners.samza.SamzaRunner;
-import org.apache.beam.sdk.Pipeline;
-import theodolite.commons.beam.AbstractBeamService;
-
-/**
- * Implementation of the use case Hierarchical Aggregation using Apache Beam with the Samza
- * Runner. To run locally in standalone start Kafka, Zookeeper, the schema-registry and the
- * workload generator using the delayed_startup.sh script. Add
- * --configFactory=org.apache.samza.config.factories.PropertiesConfigFactory
- * --configFilePath=${workspace_loc:uc4-application-samza}/config/standalone_local.properties
- * --samzaExecutionEnvironment=STANDALONE --maxSourceParallelism=1024 --as program arguments. To
- * persist logs add ${workspace_loc:/uc4-application-samza/eclipseConsoleLogs.log} as Output File
- * under Standard Input Output in Common in the Run Configuration Start via Eclipse Run.
- */
-public final class Uc4BeamSamza extends AbstractBeamService {
-
-
-  /**
-   * Private constructor setting specific options for this use case.
-   */
-  private Uc4BeamSamza(final String[] args) { //NOPMD
-    super(args);
-    this.options.setRunner(SamzaRunner.class);
-  }
-
-  /**
-   * Start running this microservice.
-   */
-  public static void main(final String[] args) {
-
-    final Uc4BeamSamza uc4BeamSamza = new Uc4BeamSamza(args);
-
-    final Pipeline pipeline = new Uc4BeamPipeline(uc4BeamSamza.options, uc4BeamSamza.getConfig());
-
-    pipeline.run().waitUntilFinish();
-  }
-
-}
diff --git a/theodolite-benchmarks/uc4-beam-samza/src/main/java/rocks/theodolite/benchmarks/uc4/beam/samza/Uc4BeamSamza.java b/theodolite-benchmarks/uc4-beam-samza/src/main/java/rocks/theodolite/benchmarks/uc4/beam/samza/Uc4BeamSamza.java
new file mode 100644
index 0000000000000000000000000000000000000000..585e3ff9589c0262c12b6fa33023cd69b58c53f1
--- /dev/null
+++ b/theodolite-benchmarks/uc4-beam-samza/src/main/java/rocks/theodolite/benchmarks/uc4/beam/samza/Uc4BeamSamza.java
@@ -0,0 +1,28 @@
+package rocks.theodolite.benchmarks.uc4.beam.samza;
+
+import org.apache.beam.runners.samza.SamzaRunner;
+import rocks.theodolite.benchmarks.commons.beam.BeamService;
+import rocks.theodolite.benchmarks.uc4.beam.PipelineFactory;
+
+/**
+ * Implementation of the use case Hierarchical Aggregation using Apache Beam with the Samza Runner.
+ * To run locally in standalone start Kafka, Zookeeper, the schema-registry and the workload
+ * generator using the delayed_startup.sh script. Add
+ * --configFactory=org.apache.samza.config.factories.PropertiesConfigFactory
+ * --configFilePath=${workspace_loc:uc4-application-samza}/config/standalone_local.properties
+ * --samzaExecutionEnvironment=STANDALONE --maxSourceParallelism=1024 --as program arguments. To
+ * persist logs add ${workspace_loc:/uc4-application-samza/eclipseConsoleLogs.log} as Output File
+ * under Standard Input Output in Common in the Run Configuration Start via Eclipse Run.
+ */
+public final class Uc4BeamSamza {
+
+  private Uc4BeamSamza() {}
+
+  /**
+   * Start running this microservice.
+   */
+  public static void main(final String[] args) {
+    new BeamService(PipelineFactory.factory(), SamzaRunner.class, args).runStandalone();
+  }
+
+}
diff --git a/theodolite-benchmarks/uc4-beam-samza/src/main/resources/META-INF/application.properties b/theodolite-benchmarks/uc4-beam-samza/src/main/resources/META-INF/application.properties
deleted file mode 100644
index bc679580dadf969e181b6787e8287066426be7e2..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc4-beam-samza/src/main/resources/META-INF/application.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-application.name=theodolite-uc4-application
-application.version=0.0.1
-
-kafka.bootstrap.servers=localhost:9092
-kafka.input.topic=input
-kafka.output.topic=output
-kafka.configuration.topic=configuration
-kafka.feedback.topic=aggregation-feedback
-kafka.window.duration.minutes=1
-
-schema.registry.url=http://localhost:8081
-
-aggregation.duration.days=30
-aggregation.advance.days=1
-
-trigger.interval=15
-grace.period.ms=270
-
-num.threads=1
-commit.interval.ms=1000
-cache.max.bytes.buffering=-1
-
-specific.avro.reader=True
-enable.auto.commit.config=True
-auto.offset.reset.config=earliest
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc4-beam/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc4-beam/.settings/org.eclipse.jdt.ui.prefs
index 32e18c393f53a0b0b3207bb896ec0e4211b27bf0..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc4-beam/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc4-beam/.settings/org.eclipse.jdt.ui.prefs
@@ -105,6 +105,7 @@ cleanup.strictly_equal_or_different=false
 cleanup.stringbuffer_to_stringbuilder=false
 cleanup.stringbuilder=false
 cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
 cleanup.substring=false
 cleanup.switch=false
 cleanup.system_property=false
@@ -166,11 +167,11 @@ sp_cleanup.boolean_literal=false
 sp_cleanup.boolean_value_rather_than_comparison=false
 sp_cleanup.break_loop=false
 sp_cleanup.collection_cloning=false
-sp_cleanup.comparing_on_criteria=false
+sp_cleanup.comparing_on_criteria=true
 sp_cleanup.comparison_statement=false
 sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
-sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.convert_to_enhanced_for_loop=true
 sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
 sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
@@ -191,7 +192,7 @@ sp_cleanup.invert_equals=false
 sp_cleanup.join=false
 sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
-sp_cleanup.make_parameters_final=false
+sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
@@ -235,7 +236,7 @@ sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
 sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
-sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
 sp_cleanup.remove_unused_local_variables=false
 sp_cleanup.remove_unused_private_fields=true
@@ -252,7 +253,8 @@ sp_cleanup.static_inner_class=false
 sp_cleanup.strictly_equal_or_different=false
 sp_cleanup.stringbuffer_to_stringbuilder=false
 sp_cleanup.stringbuilder=false
-sp_cleanup.stringbuilder_for_local_vars=true
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
 sp_cleanup.substring=false
 sp_cleanup.switch=false
 sp_cleanup.system_property=false
@@ -279,6 +281,6 @@ sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
 sp_cleanup.use_unboxing=false
 sp_cleanup.use_var=false
-sp_cleanup.useless_continue=false
-sp_cleanup.useless_return=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
 sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc4-beam/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc4-beam/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc4-beam/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc4-beam/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc4-beam/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc4-beam/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc4-beam/build.gradle b/theodolite-benchmarks/uc4-beam/build.gradle
index 502e94fa737fb2ae1bab861407b27575cd8766ca..3e9d917cc3586e5df2c5645f1d2cbcf03e3993e4 100644
--- a/theodolite-benchmarks/uc4-beam/build.gradle
+++ b/theodolite-benchmarks/uc4-beam/build.gradle
@@ -2,4 +2,6 @@ plugins {
   id 'theodolite.beam'
 }
 
-
+dependencies {
+  implementation ('io.confluent:kafka-streams-avro-serde:5.3.2') 
+}
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/application/AggregatedActivePowerRecordEventTimePolicy.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/AggregatedActivePowerRecordEventTimePolicy.java
similarity index 96%
rename from theodolite-benchmarks/uc4-beam/src/main/java/application/AggregatedActivePowerRecordEventTimePolicy.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/AggregatedActivePowerRecordEventTimePolicy.java
index dad9eca7d8d50d1b85932ddaa7ffc99418a4b759..3af4957aa210a5f6a184bf4b513202dd4087567f 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/application/AggregatedActivePowerRecordEventTimePolicy.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/AggregatedActivePowerRecordEventTimePolicy.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc4.beam;
 
 import java.util.Optional;
 import org.apache.beam.sdk.io.kafka.KafkaRecord;
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/application/AggregatedToActive.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/AggregatedToActive.java
similarity index 94%
rename from theodolite-benchmarks/uc4-beam/src/main/java/application/AggregatedToActive.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/AggregatedToActive.java
index bddd43e1e09c54bcfc85e5cbb65d1a6487f53438..63f914dca0e6536d52ce225e791d2e3b89107394 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/application/AggregatedToActive.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/AggregatedToActive.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc4.beam;
 
 import org.apache.beam.sdk.transforms.SimpleFunction;
 import org.apache.beam.sdk.values.KV;
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/application/DuplicateAsFlatMap.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/DuplicateAsFlatMap.java
similarity index 68%
rename from theodolite-benchmarks/uc4-beam/src/main/java/application/DuplicateAsFlatMap.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/DuplicateAsFlatMap.java
index 7b66082c91b87c246d8c834249d2bc82545766f5..1b430c99bb127f0746772571443f625ae69be54d 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/application/DuplicateAsFlatMap.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/DuplicateAsFlatMap.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc4.beam;
 
 import com.google.common.base.MoreObjects;
 import java.util.Collections;
@@ -14,13 +14,18 @@ import titan.ccp.model.records.ActivePowerRecord;
 
 
 /**
- * Duplicates the Kv containing the (Children,Parents) pair as a flat map.
+ * Duplicates the {@link KV} containing the (children,parents) pairs as flatMap.
  */
-public class DuplicateAsFlatMap extends DoFn
-    <KV<String, ActivePowerRecord>, KV<SensorParentKey, ActivePowerRecord>> {
+public class DuplicateAsFlatMap
+    extends DoFn<KV<String, ActivePowerRecord>, KV<SensorParentKey, ActivePowerRecord>> {
+
   private static final long serialVersionUID = -5132355515723961647L;
-  @StateId("parents")
-  private final StateSpec<ValueState<Set<String>>> parents = StateSpecs.value();//NOPMD
+
+  private static final String STATE_STORE_NAME = "DuplicateParents";
+
+  @StateId(STATE_STORE_NAME)
+  private final StateSpec<ValueState<Set<String>>> parents = StateSpecs.value(); // NOPMD
+
   private final PCollectionView<Map<String, Set<String>>> childParentPairMap;
 
   public DuplicateAsFlatMap(final PCollectionView<Map<String, Set<String>>> childParentPairMap) {
@@ -28,21 +33,21 @@ public class DuplicateAsFlatMap extends DoFn
     this.childParentPairMap = childParentPairMap;
   }
 
-
   /**
-   *  Generate a KV-pair for every child-parent match.
+   * Generate a KV-pair for every child-parent match.
    */
   @ProcessElement
-  public void processElement(@Element final KV<String, ActivePowerRecord> kv,
-                             final OutputReceiver<KV<SensorParentKey, ActivePowerRecord>> out,
-                             @StateId("parents") final ValueState<Set<String>> state,
-                             final ProcessContext c) {
+  public void processElement(
+      @Element final KV<String, ActivePowerRecord> kv,
+      final OutputReceiver<KV<SensorParentKey, ActivePowerRecord>> out,
+      @StateId(STATE_STORE_NAME) final ValueState<Set<String>> state,
+      final ProcessContext c) {
 
     final ActivePowerRecord record = kv.getValue() == null ? null : kv.getValue();
     final Set<String> newParents =
-        c.sideInput(childParentPairMap).get(kv.getKey()) == null
+        c.sideInput(this.childParentPairMap).get(kv.getKey()) == null
             ? Collections.emptySet()
-            : c.sideInput(childParentPairMap).get(kv.getKey());
+            : c.sideInput(this.childParentPairMap).get(kv.getKey());
     final Set<String> oldParents =
         MoreObjects.firstNonNull(state.read(), Collections.emptySet());
     // Forward new Pairs if they exist
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/application/FilterEvents.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/FilterEvents.java
similarity index 92%
rename from theodolite-benchmarks/uc4-beam/src/main/java/application/FilterEvents.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/FilterEvents.java
index 3588443393fdef2e0fd1bf5f1e7c497e5030cf77..6a96d7270640c1cfa3a162e0d506792d577103c5 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/application/FilterEvents.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/FilterEvents.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc4.beam;
 
 import org.apache.beam.sdk.transforms.SerializableFunction;
 import org.apache.beam.sdk.values.KV;
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/application/FilterNullValues.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/FilterNullValues.java
similarity index 91%
rename from theodolite-benchmarks/uc4-beam/src/main/java/application/FilterNullValues.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/FilterNullValues.java
index 143294f1ff2bfeea77c40ce38cd10ce3eb44be49..9aa48d7b8f6fdc64aad205821ec4db25f606156b 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/application/FilterNullValues.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/FilterNullValues.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc4.beam;
 
 import org.apache.beam.sdk.transforms.SerializableFunction;
 import org.apache.beam.sdk.values.KV;
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/application/GenerateParentsFn.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/GenerateParentsFn.java
similarity index 94%
rename from theodolite-benchmarks/uc4-beam/src/main/java/application/GenerateParentsFn.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/GenerateParentsFn.java
index 68cf551af9c681c586ebc6026c043ae8c9befbc5..e6f01c3d59c5c92f5d0c51ac807a76f0a37612b1 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/application/GenerateParentsFn.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/GenerateParentsFn.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc4.beam;
 
 import java.util.Collections;
 import java.util.Iterator;
@@ -8,8 +8,6 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.apache.beam.sdk.transforms.DoFn;
 import org.apache.beam.sdk.values.KV;
-// import theodolite.uc2.streamprocessing.KeyValue;
-// import theodolite.uc2.streamprocessing.KeyValueIterator;
 import titan.ccp.configuration.events.Event;
 import titan.ccp.model.sensorregistry.AggregatedSensor;
 import titan.ccp.model.sensorregistry.Sensor;
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/application/Uc4BeamPipeline.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/PipelineFactory.java
similarity index 53%
rename from theodolite-benchmarks/uc4-beam/src/main/java/application/Uc4BeamPipeline.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/PipelineFactory.java
index 7179fe5da937280d5baf72cd73cc392ef15a60e0..42d12d82026df0682f771b0cec5c1705ead83b2e 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/application/Uc4BeamPipeline.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/PipelineFactory.java
@@ -1,9 +1,13 @@
-package application; // NOPMD
+package rocks.theodolite.benchmarks.uc4.beam; // NOPMD
 
 import com.google.common.math.StatsAccumulator;
+import io.confluent.kafka.serializers.AbstractKafkaAvroSerDeConfig;
+import io.confluent.kafka.serializers.KafkaAvroDeserializerConfig;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
+import org.apache.beam.sdk.Pipeline;
 import org.apache.beam.sdk.coders.AvroCoder;
 import org.apache.beam.sdk.coders.CoderRegistry;
 import org.apache.beam.sdk.coders.SetCoder;
@@ -31,74 +35,82 @@ import org.apache.commons.configuration2.Configuration;
 import org.apache.kafka.clients.consumer.ConsumerConfig;
 import org.apache.kafka.common.serialization.StringDeserializer;
 import org.joda.time.Duration;
-import serialization.AggregatedActivePowerRecordCoder;
-import serialization.AggregatedActivePowerRecordDeserializer;
-import serialization.AggregatedActivePowerRecordSerializer;
-import serialization.EventCoder;
-import serialization.EventDeserializer;
-import serialization.SensorParentKeyCoder;
-import theodolite.commons.beam.AbstractPipeline;
-import theodolite.commons.beam.ConfigurationKeys;
-import theodolite.commons.beam.kafka.KafkaActivePowerTimestampReader;
-import theodolite.commons.beam.kafka.KafkaGenericReader;
-import theodolite.commons.beam.kafka.KafkaWriterTransformation;
+import rocks.theodolite.benchmarks.commons.beam.AbstractPipelineFactory;
+import rocks.theodolite.benchmarks.commons.beam.ConfigurationKeys;
+import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaActivePowerTimestampReader;
+import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaGenericReader;
+import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaWriterTransformation;
+import rocks.theodolite.benchmarks.uc4.beam.serialization.AggregatedActivePowerRecordCoder;
+import rocks.theodolite.benchmarks.uc4.beam.serialization.AggregatedActivePowerRecordDeserializer;
+import rocks.theodolite.benchmarks.uc4.beam.serialization.AggregatedActivePowerRecordSerializer;
+import rocks.theodolite.benchmarks.uc4.beam.serialization.EventCoder;
+import rocks.theodolite.benchmarks.uc4.beam.serialization.EventDeserializer;
+import rocks.theodolite.benchmarks.uc4.beam.serialization.SensorParentKeyCoder;
 import titan.ccp.configuration.events.Event;
 import titan.ccp.model.records.ActivePowerRecord;
 import titan.ccp.model.records.AggregatedActivePowerRecord;
 
 /**
- * Implementation of the use case Hierarchical Aggregation using Apache Beam.
+ * {@link AbstractPipelineFactory} for UC4.
  */
-public final class Uc4BeamPipeline extends AbstractPipeline {
+public class PipelineFactory extends AbstractPipelineFactory {
 
-  protected Uc4BeamPipeline(final PipelineOptions options, final Configuration config) { // NOPMD
-    super(options, config);
-
-    // Additional needed variables
-    final String feedbackTopic = config.getString(ConfigurationKeys.KAFKA_FEEDBACK_TOPIC);
-    final String outputTopic = config.getString(ConfigurationKeys.KAFKA_OUTPUT_TOPIC);
-    final String configurationTopic = config.getString(ConfigurationKeys.KAFKA_CONFIGURATION_TOPIC);
+  public PipelineFactory(final Configuration configuration) {
+    super(configuration);
+  }
 
-    final Duration duration =
-        Duration.standardSeconds(config.getInt(ConfigurationKeys.KAFKA_WINDOW_DURATION_MINUTES));
-    final Duration triggerDelay =
-        Duration.standardSeconds(config.getInt(ConfigurationKeys.TRIGGER_INTERVAL));
-    final Duration gracePeriod =
-        Duration.standardSeconds(config.getInt(ConfigurationKeys.GRACE_PERIOD_MS));
+  @Override
+  protected void expandOptions(final PipelineOptions options) {
+    // No options to set
+  }
 
-    // Build kafka configuration
-    final Map<String, Object> consumerConfig = this.buildConsumerConfig();
-    final Map<String, Object> configurationConfig = this.configurationConfig(config);
+  @Override
+  protected void constructPipeline(final Pipeline pipeline) { // NOPMD
+    // Additional needed variables
+    final String feedbackTopic = this.config.getString(ConfigurationKeys.KAFKA_FEEDBACK_TOPIC);
+    final String outputTopic = this.config.getString(ConfigurationKeys.KAFKA_OUTPUT_TOPIC);
+    final String configurationTopic =
+        this.config.getString(ConfigurationKeys.KAFKA_CONFIGURATION_TOPIC);
 
-    // Set Coders for Classes that will be distributed
-    final CoderRegistry cr = this.getCoderRegistry();
-    registerCoders(cr);
+    final Duration duration = Duration.standardSeconds(
+        this.config.getInt(ConfigurationKeys.KAFKA_WINDOW_DURATION_MINUTES));
+    final Duration triggerDelay = Duration.standardSeconds(
+        this.config.getInt(ConfigurationKeys.TRIGGER_INTERVAL));
+    final Duration gracePeriod = Duration.standardSeconds(
+        this.config.getInt(ConfigurationKeys.GRACE_PERIOD_MS));
 
     // Read from Kafka
+    final String bootstrapServer = this.config.getString(ConfigurationKeys.KAFKA_BOOTSTRAP_SERVERS);
+
     // ActivePowerRecords
-    final KafkaActivePowerTimestampReader kafkaActivePowerRecordReader =
-        new KafkaActivePowerTimestampReader(this.bootstrapServer, this.inputTopic, consumerConfig);
+    final KafkaActivePowerTimestampReader kafkaActivePowerRecordReader = super.buildKafkaReader();
 
     // Configuration Events
     final KafkaGenericReader<Event, String> kafkaConfigurationReader =
         new KafkaGenericReader<>(
-            this.bootstrapServer, configurationTopic, configurationConfig,
-            EventDeserializer.class, StringDeserializer.class);
-
-    // Transform into AggregatedActivePowerRecords into ActivePowerRecords
-    final AggregatedToActive aggregatedToActive = new AggregatedToActive();
+            bootstrapServer,
+            configurationTopic,
+            this.configurationConfig(),
+            EventDeserializer.class,
+            StringDeserializer.class);
 
     // Write to Kafka
     final KafkaWriterTransformation<AggregatedActivePowerRecord> kafkaOutput =
         new KafkaWriterTransformation<>(
-            this.bootstrapServer, outputTopic, AggregatedActivePowerRecordSerializer.class);
+            bootstrapServer,
+            outputTopic,
+            AggregatedActivePowerRecordSerializer.class,
+            this.buildProducerConfig());
 
     final KafkaWriterTransformation<AggregatedActivePowerRecord> kafkaFeedback =
         new KafkaWriterTransformation<>(
-            this.bootstrapServer, feedbackTopic, AggregatedActivePowerRecordSerializer.class);
+            bootstrapServer,
+            feedbackTopic,
+            AggregatedActivePowerRecordSerializer.class,
+            this.buildProducerConfig());
 
     // Apply pipeline transformations
-    final PCollection<KV<String, ActivePowerRecord>> values = this
+    final PCollection<KV<String, ActivePowerRecord>> values = pipeline
         .apply("Read from Kafka", kafkaActivePowerRecordReader)
         .apply("Read Windows", Window.into(FixedWindows.of(duration)))
         .apply("Set trigger for input", Window
@@ -110,12 +122,15 @@ public final class Uc4BeamPipeline extends AbstractPipeline {
             .discardingFiredPanes());
 
     // Read the results of earlier aggregations.
-    final PCollection<KV<String, ActivePowerRecord>> aggregationsInput = this
+    final PCollection<KV<String, ActivePowerRecord>> aggregationsInput = pipeline
         .apply("Read aggregation results", KafkaIO.<String, AggregatedActivePowerRecord>read()
-            .withBootstrapServers(this.bootstrapServer)
+            .withBootstrapServers(bootstrapServer)
             .withTopic(feedbackTopic)
             .withKeyDeserializer(StringDeserializer.class)
-            .withValueDeserializer(AggregatedActivePowerRecordDeserializer.class)
+            .withValueDeserializerAndCoder(
+                AggregatedActivePowerRecordDeserializer.class,
+                AvroCoder.of(AggregatedActivePowerRecord.class))
+            .withConsumerConfigUpdates(this.buildConsumerConfig())
             .withTimestampPolicyFactory(
                 (tp, previousWaterMark) -> new AggregatedActivePowerRecordEventTimePolicy(
                     previousWaterMark))
@@ -123,11 +138,12 @@ public final class Uc4BeamPipeline extends AbstractPipeline {
         .apply("Apply Windows", Window.into(FixedWindows.of(duration)))
         // Convert into the correct data format
         .apply("Convert AggregatedActivePowerRecord to ActivePowerRecord",
-            MapElements.via(aggregatedToActive))
+            MapElements.via(new AggregatedToActive()))
         .apply("Set trigger for feedback", Window
             .<KV<String, ActivePowerRecord>>configure()
             .triggering(Repeatedly.forever(
-                AfterProcessingTime.pastFirstElementInPane()
+                AfterProcessingTime
+                    .pastFirstElementInPane()
                     .plusDelayOf(triggerDelay)))
             .withAllowedLateness(gracePeriod)
             .discardingFiredPanes());
@@ -142,7 +158,7 @@ public final class Uc4BeamPipeline extends AbstractPipeline {
             Flatten.pCollections());
 
     // Build the configuration stream from a changelog.
-    final PCollection<KV<String, Set<String>>> configurationStream = this
+    final PCollection<KV<String, Set<String>>> configurationStream = pipeline
         .apply("Read sensor groups", kafkaConfigurationReader)
         // Only forward relevant changes in the hierarchy
         .apply("Filter changed and status events",
@@ -170,17 +186,13 @@ public final class Uc4BeamPipeline extends AbstractPipeline {
                 .accumulatingFiredPanes())
             .apply(View.asMap());
 
-    final FilterNullValues filterNullValues = new FilterNullValues();
-
     // Build pairs of every sensor reading and parent
     final PCollection<KV<SensorParentKey, ActivePowerRecord>> flatMappedValues =
         inputCollection.apply(
             "Duplicate as flatMap",
-            ParDo.of(new DuplicateAsFlatMap(childParentPairMap))
-                .withSideInputs(childParentPairMap))
+            ParDo.of(new DuplicateAsFlatMap(childParentPairMap)).withSideInputs(childParentPairMap))
             .apply("Filter only latest changes", Latest.perKey())
-            .apply("Filter out null values",
-                Filter.by(filterNullValues));
+            .apply("Filter out null values", Filter.by(new FilterNullValues()));
 
     final SetIdForAggregated setIdForAggregated = new SetIdForAggregated();
     final SetKeyToGroup setKeyToGroup = new SetKeyToGroup();
@@ -204,9 +216,30 @@ public final class Uc4BeamPipeline extends AbstractPipeline {
 
     aggregations.apply("Write to aggregation results", kafkaOutput);
 
-    aggregations
-        .apply("Write to feedback topic", kafkaFeedback);
+    aggregations.apply("Write to feedback topic", kafkaFeedback);
+  }
 
+  @Override
+  protected void registerCoders(final CoderRegistry registry) {
+    registry.registerCoderForClass(
+        ActivePowerRecord.class,
+        // AvroCoder.of(ActivePowerRecord.SCHEMA$));
+        AvroCoder.of(ActivePowerRecord.class, false));
+    registry.registerCoderForClass(
+        AggregatedActivePowerRecord.class,
+        new AggregatedActivePowerRecordCoder());
+    registry.registerCoderForClass(
+        Set.class,
+        SetCoder.of(StringUtf8Coder.of()));
+    registry.registerCoderForClass(
+        Event.class,
+        new EventCoder());
+    registry.registerCoderForClass(
+        SensorParentKey.class,
+        new SensorParentKeyCoder());
+    registry.registerCoderForClass(
+        StatsAccumulator.class,
+        AvroCoder.of(StatsAccumulator.class));
   }
 
 
@@ -215,34 +248,58 @@ public final class Uc4BeamPipeline extends AbstractPipeline {
    *
    * @return the build configuration.
    */
-  public Map<String, Object> configurationConfig(final Configuration config) {
+  private Map<String, Object> configurationConfig() {
     final Map<String, Object> consumerConfig = new HashMap<>();
-    consumerConfig.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,
-        config.getString(ConfigurationKeys.ENABLE_AUTO_COMMIT_CONFIG));
-    consumerConfig.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,
-        config
-            .getString(ConfigurationKeys.AUTO_OFFSET_RESET_CONFIG));
-
-    consumerConfig.put(ConsumerConfig.GROUP_ID_CONFIG, config
-        .getString(ConfigurationKeys.APPLICATION_NAME) + "-configuration");
+    consumerConfig.put(
+        ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,
+        this.config.getString(ConfigurationKeys.ENABLE_AUTO_COMMIT));
+    consumerConfig.put(
+        ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,
+        this.config.getString(ConfigurationKeys.AUTO_OFFSET_RESET));
+    consumerConfig.put(
+        ConsumerConfig.GROUP_ID_CONFIG, this.config
+            .getString(ConfigurationKeys.APPLICATION_NAME) + "-configuration");
     return consumerConfig;
   }
 
+  private Map<String, Object> buildConsumerConfig() {
+    final Map<String, Object> consumerConfig = new HashMap<>();
+    consumerConfig.put(
+        ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,
+        this.config.getString(ConfigurationKeys.ENABLE_AUTO_COMMIT));
+    consumerConfig.put(
+        ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,
+        this.config.getString(ConfigurationKeys.AUTO_OFFSET_RESET));
+    consumerConfig.put(
+        AbstractKafkaAvroSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG,
+        this.config.getString(ConfigurationKeys.SCHEMA_REGISTRY_URL));
+    consumerConfig.put(
+        KafkaAvroDeserializerConfig.SPECIFIC_AVRO_READER_CONFIG,
+        this.config.getString(ConfigurationKeys.SPECIFIC_AVRO_READER));
+    consumerConfig.put(
+        ConsumerConfig.GROUP_ID_CONFIG,
+        this.config.getString(ConfigurationKeys.APPLICATION_NAME));
+    return consumerConfig;
+  }
 
   /**
-   * Registers all Coders for all needed Coders.
+   * Builds a simple configuration for a Kafka producer transformation.
    *
-   * @param cr CoderRegistry.
+   * @return the build configuration.
    */
-  private static void registerCoders(final CoderRegistry cr) {
-    cr.registerCoderForClass(ActivePowerRecord.class,
-        AvroCoder.of(ActivePowerRecord.class));
-    cr.registerCoderForClass(AggregatedActivePowerRecord.class,
-        new AggregatedActivePowerRecordCoder());
-    cr.registerCoderForClass(Set.class, SetCoder.of(StringUtf8Coder.of()));
-    cr.registerCoderForClass(Event.class, new EventCoder());
-    cr.registerCoderForClass(SensorParentKey.class, new SensorParentKeyCoder());
-    cr.registerCoderForClass(StatsAccumulator.class, AvroCoder.of(StatsAccumulator.class));
+  private Map<String, Object> buildProducerConfig() {
+    final Map<String, Object> config = new HashMap<>();
+    config.put(
+        AbstractKafkaAvroSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG,
+        this.config.getString(ConfigurationKeys.SCHEMA_REGISTRY_URL));
+    config.put(
+        KafkaAvroDeserializerConfig.SPECIFIC_AVRO_READER_CONFIG,
+        this.config.getString(ConfigurationKeys.SPECIFIC_AVRO_READER));
+    return config;
   }
-}
 
+  public static Function<Configuration, AbstractPipelineFactory> factory() {
+    return config -> new PipelineFactory(config);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/application/RecordAggregation.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/RecordAggregation.java
similarity index 97%
rename from theodolite-benchmarks/uc4-beam/src/main/java/application/RecordAggregation.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/RecordAggregation.java
index 16fd411b44cc1f955b255be870215ac120bce193..6fbf6ff3f3abcdfd4f5ca0de93d68c2532655b4d 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/application/RecordAggregation.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/RecordAggregation.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc4.beam;
 
 import java.io.Serializable;
 import org.apache.beam.sdk.coders.AvroCoder;
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/application/SensorParentKey.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SensorParentKey.java
similarity index 93%
rename from theodolite-benchmarks/uc4-beam/src/main/java/application/SensorParentKey.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SensorParentKey.java
index 546fc04c2de089a28d8f0fba86a7fbcd5c1cc0a8..28efd63f2cecbc40f9e9fcb3f59301fd86c5909a 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/application/SensorParentKey.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SensorParentKey.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc4.beam;
 
 /**
  * A key consisting of the identifier of a sensor and an identifier of parent sensor.
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/application/SetIdForAggregated.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SetIdForAggregated.java
similarity index 94%
rename from theodolite-benchmarks/uc4-beam/src/main/java/application/SetIdForAggregated.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SetIdForAggregated.java
index 0279a26ed925408b5383be50a202f5c88cea53aa..23ebb6d0104ef3992b4e2a4763dd23e722fe30f9 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/application/SetIdForAggregated.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SetIdForAggregated.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc4.beam;
 
 import org.apache.beam.sdk.transforms.SimpleFunction;
 import org.apache.beam.sdk.values.KV;
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/application/SetKeyToGroup.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SetKeyToGroup.java
similarity index 92%
rename from theodolite-benchmarks/uc4-beam/src/main/java/application/SetKeyToGroup.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SetKeyToGroup.java
index 7d8dc70583fb45e02a5a8091b92d724bb22b4a78..3ffba12823aca2da88250eb601615de1ac5177e2 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/application/SetKeyToGroup.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SetKeyToGroup.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc4.beam;
 
 import org.apache.beam.sdk.transforms.SimpleFunction;
 import org.apache.beam.sdk.values.KV;
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/application/UpdateChildParentPairs.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/UpdateChildParentPairs.java
similarity index 67%
rename from theodolite-benchmarks/uc4-beam/src/main/java/application/UpdateChildParentPairs.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/UpdateChildParentPairs.java
index 8692be5ae6637ebda86f10d66b43c6071264e099..190bb074d4430f23aeabcd123d1f1c4bc937cd0d 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/application/UpdateChildParentPairs.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/UpdateChildParentPairs.java
@@ -1,4 +1,4 @@
-package application;
+package rocks.theodolite.benchmarks.uc4.beam;
 
 import java.util.Set;
 import org.apache.beam.sdk.state.StateSpec;
@@ -12,11 +12,12 @@ import org.apache.beam.sdk.values.KV;
  */
 public class UpdateChildParentPairs extends DoFn<KV<String, Set<String>>, KV<String, Set<String>>> {
 
+  private static final String STATE_STORE_NAME = "UpdateParents";
+
   private static final long serialVersionUID = 1L;
 
-  @StateId("parents")
-  private final StateSpec<ValueState<Set<String>>> parents = // NOPMD
-      StateSpecs.value();
+  @StateId(STATE_STORE_NAME)
+  private final StateSpec<ValueState<Set<String>>> parents = StateSpecs.value(); // NOPMD
 
   /**
    * Match the changes accordingly.
@@ -24,9 +25,10 @@ public class UpdateChildParentPairs extends DoFn<KV<String, Set<String>>, KV<Str
    * @param kv the sensor parents set that contains the changes.
    */
   @ProcessElement
-  public void processElement(@Element final KV<String, Set<String>> kv,
+  public void processElement(
+      @Element final KV<String, Set<String>> kv,
       final OutputReceiver<KV<String, Set<String>>> out,
-      @StateId("parents") final ValueState<Set<String>> state) {
+      @StateId(STATE_STORE_NAME) final ValueState<Set<String>> state) {
     if (kv.getValue() == null || !kv.getValue().equals(state.read())) {
       out.output(kv);
       state.write(kv.getValue());
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/serialization/AggregatedActivePowerRecordCoder.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordCoder.java
similarity index 89%
rename from theodolite-benchmarks/uc4-beam/src/main/java/serialization/AggregatedActivePowerRecordCoder.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordCoder.java
index d2b484f5ab30be63f311d6dbcf495baebbd5e2b4..f460d42de2042064952434f6bf044920f217138a 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/serialization/AggregatedActivePowerRecordCoder.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordCoder.java
@@ -1,4 +1,4 @@
-package serialization;
+package rocks.theodolite.benchmarks.uc4.beam.serialization;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -11,8 +11,7 @@ import org.apache.beam.sdk.coders.CoderException;
 import titan.ccp.model.records.AggregatedActivePowerRecord;
 
 /**
- * Wrapper Class that encapsulates a AggregatedActivePowerRecord Serde in a
- * org.apache.beam.sdk.coders.Coder.
+ * {@link Coder} for an {@link AggregatedActivePowerRecord}.
  */
 @SuppressWarnings("serial")
 public class AggregatedActivePowerRecordCoder extends Coder<AggregatedActivePowerRecord>
@@ -45,13 +44,13 @@ public class AggregatedActivePowerRecordCoder extends Coder<AggregatedActivePowe
 
   @Override
   public List<? extends Coder<?>> getCoderArguments() {
-    return null;
+    return List.of();
   }
 
   @Override
   public void verifyDeterministic() throws NonDeterministicException {
     if (!DETERMINISTIC) {
-      throw new NonDeterministicException(this, "This class should be deterministic!");
+      throw new NonDeterministicException(this, "This class should be deterministic.");
     }
   }
 }
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordDeserializer.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordDeserializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c481f8e6f68a3a0decbcb73c3751f464646b7cf
--- /dev/null
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordDeserializer.java
@@ -0,0 +1,12 @@
+package rocks.theodolite.benchmarks.uc4.beam.serialization;
+
+import io.confluent.kafka.streams.serdes.avro.SpecificAvroDeserializer;
+import org.apache.kafka.common.serialization.Deserializer;
+import titan.ccp.model.records.AggregatedActivePowerRecord;
+
+/**
+ * {@link Deserializer} for an {@link AggregatedActivePowerRecord}.
+ */
+public class AggregatedActivePowerRecordDeserializer
+    extends SpecificAvroDeserializer<AggregatedActivePowerRecord> {
+}
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordSerializer.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..073c3d0f94c24872460ae58c6236a0c4e19e0d5d
--- /dev/null
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordSerializer.java
@@ -0,0 +1,12 @@
+package rocks.theodolite.benchmarks.uc4.beam.serialization;
+
+import io.confluent.kafka.streams.serdes.avro.SpecificAvroSerializer;
+import org.apache.kafka.common.serialization.Serializer;
+import titan.ccp.model.records.AggregatedActivePowerRecord;
+
+/**
+ * {@link Serializer} for an {@link AggregatedActivePowerRecord}.
+ */
+public class AggregatedActivePowerRecordSerializer
+    extends SpecificAvroSerializer<AggregatedActivePowerRecord> {
+}
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/serialization/EventCoder.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/EventCoder.java
similarity index 97%
rename from theodolite-benchmarks/uc4-beam/src/main/java/serialization/EventCoder.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/EventCoder.java
index 710beb71dc8776e6309028327b05307aa590a7f6..b96398398e61f3db0f0632f8384d11f30ccc7aca 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/serialization/EventCoder.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/EventCoder.java
@@ -1,4 +1,4 @@
-package serialization;
+package rocks.theodolite.benchmarks.uc4.beam.serialization;
 
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/serialization/EventDeserializer.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/EventDeserializer.java
similarity index 94%
rename from theodolite-benchmarks/uc4-beam/src/main/java/serialization/EventDeserializer.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/EventDeserializer.java
index 34e31a3059d0749848a30979f32e6df6651c1b47..ae9c480e1c76949f8cfa5d27c73282e270232d0a 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/serialization/EventDeserializer.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/EventDeserializer.java
@@ -1,4 +1,4 @@
-package serialization;
+package rocks.theodolite.benchmarks.uc4.beam.serialization;
 
 import java.util.Map;
 import org.apache.kafka.common.serialization.ByteBufferDeserializer;
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/serialization/SensorParentKeyCoder.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/SensorParentKeyCoder.java
similarity index 94%
rename from theodolite-benchmarks/uc4-beam/src/main/java/serialization/SensorParentKeyCoder.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/SensorParentKeyCoder.java
index 3e85c3242fb854bef514787c92bb58ad76526cb4..b75037bce24b5b5ab07c9ef6818c0739f68544b2 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/serialization/SensorParentKeyCoder.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/SensorParentKeyCoder.java
@@ -1,6 +1,5 @@
-package serialization;
+package rocks.theodolite.benchmarks.uc4.beam.serialization;
 
-import application.SensorParentKey;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -11,6 +10,7 @@ import java.util.List;
 import org.apache.beam.sdk.coders.Coder;
 import org.apache.beam.sdk.coders.CoderException;
 import org.apache.kafka.common.serialization.Serde;
+import rocks.theodolite.benchmarks.uc4.beam.SensorParentKey;
 
 /**
  * Wrapper Class that encapsulates a SensorParentKey Serde in a org.apache.beam.sdk.coders.Coder.
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/serialization/SensorParentKeySerde.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/SensorParentKeySerde.java
similarity index 88%
rename from theodolite-benchmarks/uc4-beam/src/main/java/serialization/SensorParentKeySerde.java
rename to theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/SensorParentKeySerde.java
index 468adb3947439c11c4fd9b289f41b68e606bdb1d..64242b3fd2618b154e47cc46ce2fe6f9375be209 100644
--- a/theodolite-benchmarks/uc4-beam/src/main/java/serialization/SensorParentKeySerde.java
+++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/SensorParentKeySerde.java
@@ -1,7 +1,7 @@
-package serialization;
+package rocks.theodolite.benchmarks.uc4.beam.serialization;
 
-import application.SensorParentKey;
 import org.apache.kafka.common.serialization.Serde;
+import rocks.theodolite.benchmarks.uc4.beam.SensorParentKey;
 import titan.ccp.common.kafka.simpleserdes.BufferSerde;
 import titan.ccp.common.kafka.simpleserdes.ReadBuffer;
 import titan.ccp.common.kafka.simpleserdes.SimpleSerdes;
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/serialization/AggregatedActivePowerRecordDeserializer.java b/theodolite-benchmarks/uc4-beam/src/main/java/serialization/AggregatedActivePowerRecordDeserializer.java
deleted file mode 100644
index 6e2f2765ff65d3bca2a127be36db0854f15afebc..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc4-beam/src/main/java/serialization/AggregatedActivePowerRecordDeserializer.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package serialization;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import org.apache.beam.sdk.coders.AvroCoder;
-import org.apache.kafka.common.serialization.Deserializer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import titan.ccp.model.records.AggregatedActivePowerRecord;
-
-/**
- * Wrapper Class that encapsulates a IMonitoringRecordSerde.serializer in a Deserializer
- */
-public class AggregatedActivePowerRecordDeserializer
-    implements Deserializer<AggregatedActivePowerRecord> {
-
-  private static final Logger LOGGER =
-      LoggerFactory.getLogger(AggregatedActivePowerRecordDeserializer.class);
-
-  private final transient AvroCoder<AggregatedActivePowerRecord> avroEnCoder =
-      AvroCoder.of(AggregatedActivePowerRecord.class);
-
-  @Override
-  public AggregatedActivePowerRecord deserialize(final String topic, final byte[] data) {
-    AggregatedActivePowerRecord value = null;
-    try {
-      value = this.avroEnCoder.decode(new ByteArrayInputStream(data));
-    } catch (final IOException e) {
-      LOGGER.error("Could not deserialize AggregatedActivePowerRecord", e);
-    }
-    return value;
-  }
-
-}
diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/serialization/AggregatedActivePowerRecordSerializer.java b/theodolite-benchmarks/uc4-beam/src/main/java/serialization/AggregatedActivePowerRecordSerializer.java
deleted file mode 100644
index 77b79d5465f1d561870bf5b04f8fa20f87076adb..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/uc4-beam/src/main/java/serialization/AggregatedActivePowerRecordSerializer.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package serialization;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import org.apache.beam.sdk.coders.AvroCoder;
-import org.apache.kafka.common.serialization.Serializer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import titan.ccp.model.records.AggregatedActivePowerRecord;
-
-/**
- * Wrapper Class that encapsulates a IMonitoringRecordSerde.serializer in a Serializer
- */
-public class AggregatedActivePowerRecordSerializer
-    implements Serializer<AggregatedActivePowerRecord> {
-
-  private static final Logger LOGGER =
-      LoggerFactory.getLogger(AggregatedActivePowerRecordSerializer.class);
-
-  private final transient AvroCoder<AggregatedActivePowerRecord> avroEnCoder =
-      AvroCoder.of(AggregatedActivePowerRecord.class);
-
-  @Override
-  public byte[] serialize(final String topic, final AggregatedActivePowerRecord data) {
-    final ByteArrayOutputStream out = new ByteArrayOutputStream();
-    try {
-      this.avroEnCoder.encode(data, out);
-    } catch (final IOException e) {
-      LOGGER.error("Could not serialize AggregatedActivePowerRecord", e);
-    }
-    final byte[] result = out.toByteArray();
-    try {
-      out.close();
-    } catch (final IOException e) {
-      LOGGER.error(
-          "Could not close output stream after serialization of AggregatedActivePowerRecord", e);
-    }
-    return result;
-  }
-
-  @Override
-  public void close() {
-    Serializer.super.close();
-  }
-}
diff --git a/theodolite-benchmarks/uc4-beam-flink/src/main/resources/META-INF/application.properties b/theodolite-benchmarks/uc4-beam/src/main/resources/META-INF/application.properties
similarity index 83%
rename from theodolite-benchmarks/uc4-beam-flink/src/main/resources/META-INF/application.properties
rename to theodolite-benchmarks/uc4-beam/src/main/resources/META-INF/application.properties
index bc679580dadf969e181b6787e8287066426be7e2..c1a8ca17b41ab8c8f0fa939c748200db5ba7d0d2 100644
--- a/theodolite-benchmarks/uc4-beam-flink/src/main/resources/META-INF/application.properties
+++ b/theodolite-benchmarks/uc4-beam/src/main/resources/META-INF/application.properties
@@ -20,6 +20,7 @@ num.threads=1
 commit.interval.ms=1000
 cache.max.bytes.buffering=-1
 
-specific.avro.reader=True
-enable.auto.commit.config=True
-auto.offset.reset.config=earliest
\ No newline at end of file
+specific.avro.reader=true
+enable.auto.commit=true
+max.poll.records=500
+auto.offset.reset=earliest
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc4-flink/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc4-flink/.settings/org.eclipse.jdt.ui.prefs
index 272e01533f6a345d53d2635c47e38c6d3c33dc8a..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc4-flink/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc4-flink/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,25 +12,72 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
 cleanup.remove_redundant_semicolons=true
@@ -37,6 +85,7 @@ cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,28 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
 org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -80,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
-sp_cleanup.remove_redundant_modifiers=true
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -115,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc4-flink/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc4-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/uc4-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/uc4-flink/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/uc4-flink/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc4-flink/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/uc4-flink/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/uc4-flink/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc4-flink/Dockerfile b/theodolite-benchmarks/uc4-flink/Dockerfile
index 4f51f379e5da436104bb8c914e3233d6ecb4ec1f..1fe58e9930db0ef30fa10d12519dd68ccdb2e97e 100644
--- a/theodolite-benchmarks/uc4-flink/Dockerfile
+++ b/theodolite-benchmarks/uc4-flink/Dockerfile
@@ -1,3 +1,3 @@
-FROM flink:1.12-scala_2.12-java11
+FROM flink:1.13-java11
 
 ADD build/libs/uc4-flink-all.jar /opt/flink/usrlib/artifacts/uc4-flink-all.jar
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc4-flink/build.gradle b/theodolite-benchmarks/uc4-flink/build.gradle
index ebc7ca5f30a668fd161bb22f95133452b5061441..a6d20c2ddeaf8cd614d9fb3818ad8f18ba28c2a9 100644
--- a/theodolite-benchmarks/uc4-flink/build.gradle
+++ b/theodolite-benchmarks/uc4-flink/build.gradle
@@ -2,4 +2,4 @@ plugins {
   id 'theodolite.flink'
 }
 
-mainClassName = "theodolite.uc4.application.AggregationServiceFlinkJob"
+mainClassName = "rocks.theodolite.benchmarks.uc4.flink.AggregationServiceFlinkJob"
diff --git a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/AggregationServiceFlinkJob.java b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/AggregationServiceFlinkJob.java
similarity index 90%
rename from theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/AggregationServiceFlinkJob.java
rename to theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/AggregationServiceFlinkJob.java
index 3e2878a893057024de00333492462f5029eb6d77..726a7f590aaa5be4ccb6e817076da5ede21cf272 100644
--- a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/AggregationServiceFlinkJob.java
+++ b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/AggregationServiceFlinkJob.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.application; // NOPMD Imports required
+package rocks.theodolite.benchmarks.uc4.flink; // NOPMD Imports required
 
 import java.time.Duration;
 import java.util.Set;
@@ -9,23 +9,23 @@ import org.apache.flink.api.common.typeinfo.Types;
 import org.apache.flink.api.java.functions.KeySelector;
 import org.apache.flink.api.java.tuple.Tuple2;
 import org.apache.flink.runtime.state.StateBackend;
-import org.apache.flink.streaming.api.TimeCharacteristic;
 import org.apache.flink.streaming.api.datastream.DataStream;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
 import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows;
 import org.apache.flink.streaming.api.windowing.time.Time;
 import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer;
+import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumerBase;
 import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer;
 import org.apache.kafka.common.serialization.Serdes;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import theodolite.commons.flink.KafkaConnectorFactory;
-import theodolite.commons.flink.StateBackends;
-import theodolite.commons.flink.TupleType;
-import theodolite.uc4.application.util.ImmutableSensorRegistrySerializer;
-import theodolite.uc4.application.util.ImmutableSetSerializer;
-import theodolite.uc4.application.util.SensorParentKey;
-import theodolite.uc4.application.util.SensorParentKeySerializer;
+import rocks.theodolite.benchmarks.commons.flink.KafkaConnectorFactory;
+import rocks.theodolite.benchmarks.commons.flink.StateBackends;
+import rocks.theodolite.benchmarks.commons.flink.TupleType;
+import rocks.theodolite.benchmarks.uc4.flink.util.ImmutableSensorRegistrySerializer;
+import rocks.theodolite.benchmarks.uc4.flink.util.ImmutableSetSerializer;
+import rocks.theodolite.benchmarks.uc4.flink.util.SensorParentKey;
+import rocks.theodolite.benchmarks.uc4.flink.util.SensorParentKeySerializer;
 import titan.ccp.common.configuration.ServiceConfigurations;
 import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory;
 import titan.ccp.configuration.events.Event;
@@ -68,8 +68,6 @@ public final class AggregationServiceFlinkJob {
   }
 
   private void configureEnv() {
-    this.env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
-
     final boolean checkpointing = this.config.getBoolean(ConfigurationKeys.CHECKPOINTING, true);
     final int commitIntervalMs = this.config.getInt(ConfigurationKeys.COMMIT_INTERVAL_MS);
     if (checkpointing) {
@@ -103,9 +101,11 @@ public final class AggregationServiceFlinkJob {
     this.env.getConfig().registerTypeWithKryoSerializer(Set.of(1, 2, 3, 4).getClass(), // NOCS
         new ImmutableSetSerializer());
 
-    this.env.getConfig().getRegisteredTypesWithKryoSerializers()
-        .forEach((c, s) -> LOGGER.info("Class " + c.getName() + " registered with serializer "
-            + s.getSerializer().getClass().getName()));
+    this.env
+        .getConfig()
+        .getRegisteredTypesWithKryoSerializers()
+        .forEach((c, s) -> LOGGER.info("Class '{}' registered with serializer '{}'.", c.getName(),
+            s.getSerializer().getClass().getName()));
   }
 
   private void buildPipeline() {
@@ -134,12 +134,13 @@ public final class AggregationServiceFlinkJob {
     final FlinkKafkaConsumer<AggregatedActivePowerRecord> kafkaOutputSource =
         kafkaConnector.createConsumer(outputTopic, AggregatedActivePowerRecord.class);
 
-    final FlinkKafkaConsumer<Tuple2<Event, String>> kafkaConfigSource =
+    final FlinkKafkaConsumerBase<Tuple2<Event, String>> kafkaConfigSource =
         kafkaConnector.createConsumer(
             configurationTopic,
             EventSerde::serde,
             Serdes::String,
-            TupleType.of(TypeInformation.of(Event.class), Types.STRING));
+            TupleType.of(TypeInformation.of(Event.class), Types.STRING))
+            .setStartFromEarliest();
 
     // Sink to output topic with SensorId, AggregatedActivePowerRecord
     final FlinkKafkaProducer<Tuple2<String, AggregatedActivePowerRecord>> kafkaAggregationSink =
diff --git a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/ChildParentsFlatMapFunction.java b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/ChildParentsFlatMapFunction.java
similarity index 98%
rename from theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/ChildParentsFlatMapFunction.java
rename to theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/ChildParentsFlatMapFunction.java
index 910dc359fa9b5b0810f7f9b6e67bfceaa68cc798..c439df1e49381f8779a64814ae056635bd408c64 100644
--- a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/ChildParentsFlatMapFunction.java
+++ b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/ChildParentsFlatMapFunction.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.application;
+package rocks.theodolite.benchmarks.uc4.flink;
 
 import java.util.Iterator;
 import java.util.Map;
diff --git a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/ConfigurationKeys.java b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/ConfigurationKeys.java
similarity index 96%
rename from theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/ConfigurationKeys.java
rename to theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/ConfigurationKeys.java
index 448e8b095ef15c434655ca3c76a9e2de21244054..290f4341958dd133926234219017cbb9149dd3f8 100644
--- a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/ConfigurationKeys.java
+++ b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/ConfigurationKeys.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.application;
+package rocks.theodolite.benchmarks.uc4.flink;
 
 /**
  * Keys to access configuration parameters.
diff --git a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/JoinAndDuplicateCoFlatMapFunction.java b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/JoinAndDuplicateCoFlatMapFunction.java
similarity index 95%
rename from theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/JoinAndDuplicateCoFlatMapFunction.java
rename to theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/JoinAndDuplicateCoFlatMapFunction.java
index 6ef9a72e9695cfccba0bbcca1238f7ebc94fc505..624327a69feb8bce2f1b85af3e57cf5db9511e74 100644
--- a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/JoinAndDuplicateCoFlatMapFunction.java
+++ b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/JoinAndDuplicateCoFlatMapFunction.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.application;
+package rocks.theodolite.benchmarks.uc4.flink;
 
 import java.util.Set;
 import org.apache.flink.api.common.state.MapState;
@@ -9,7 +9,7 @@ import org.apache.flink.api.java.tuple.Tuple2;
 import org.apache.flink.configuration.Configuration;
 import org.apache.flink.streaming.api.functions.co.RichCoFlatMapFunction;
 import org.apache.flink.util.Collector;
-import theodolite.uc4.application.util.SensorParentKey;
+import rocks.theodolite.benchmarks.uc4.flink.util.SensorParentKey;
 import titan.ccp.model.records.ActivePowerRecord;
 
 /**
diff --git a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/RecordAggregationProcessWindowFunction.java b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/RecordAggregationProcessWindowFunction.java
similarity index 97%
rename from theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/RecordAggregationProcessWindowFunction.java
rename to theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/RecordAggregationProcessWindowFunction.java
index 45d4a09d153881572c949d2af7542f9cffb5622d..29e1ea32235ae0789e72f4931932b2697c60759b 100644
--- a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/RecordAggregationProcessWindowFunction.java
+++ b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/RecordAggregationProcessWindowFunction.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.application;
+package rocks.theodolite.benchmarks.uc4.flink;
 
 import org.apache.flink.api.common.state.MapState;
 import org.apache.flink.api.common.state.MapStateDescriptor;
@@ -11,7 +11,7 @@ import org.apache.flink.configuration.Configuration;
 import org.apache.flink.streaming.api.functions.windowing.ProcessWindowFunction;
 import org.apache.flink.streaming.api.windowing.windows.TimeWindow;
 import org.apache.flink.util.Collector;
-import theodolite.uc4.application.util.SensorParentKey;
+import rocks.theodolite.benchmarks.uc4.flink.util.SensorParentKey;
 import titan.ccp.model.records.ActivePowerRecord;
 import titan.ccp.model.records.AggregatedActivePowerRecord;
 
diff --git a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/util/ImmutableSensorRegistrySerializer.java b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/ImmutableSensorRegistrySerializer.java
similarity index 94%
rename from theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/util/ImmutableSensorRegistrySerializer.java
rename to theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/ImmutableSensorRegistrySerializer.java
index e157f35c8a052d2d4a28526a0d98d56515d586d6..54d8826900cc70a5eb86d71df7fcf9c4a4da4a7f 100644
--- a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/util/ImmutableSensorRegistrySerializer.java
+++ b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/ImmutableSensorRegistrySerializer.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.application.util;
+package rocks.theodolite.benchmarks.uc4.flink.util;
 
 import com.esotericsoftware.kryo.Kryo;
 import com.esotericsoftware.kryo.Serializer;
diff --git a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/util/ImmutableSetSerializer.java b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/ImmutableSetSerializer.java
similarity index 96%
rename from theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/util/ImmutableSetSerializer.java
rename to theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/ImmutableSetSerializer.java
index 6b2dbcdfb403705b39815dd31112deab7947d83d..4c23ffefc7e2715c68aa450a235a87bd914a5ed5 100644
--- a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/util/ImmutableSetSerializer.java
+++ b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/ImmutableSetSerializer.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.application.util;
+package rocks.theodolite.benchmarks.uc4.flink.util;
 
 import com.esotericsoftware.kryo.Kryo;
 import com.esotericsoftware.kryo.Serializer;
diff --git a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/util/SensorParentKey.java b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/SensorParentKey.java
similarity index 95%
rename from theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/util/SensorParentKey.java
rename to theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/SensorParentKey.java
index 903b66dd12a2864d522fde7eb7cf3fdc2ec73bcd..af67c35cefb20abc0bb5d96c3940db71c786f586 100644
--- a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/util/SensorParentKey.java
+++ b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/SensorParentKey.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.application.util;
+package rocks.theodolite.benchmarks.uc4.flink.util;
 
 import java.util.Objects;
 
diff --git a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/util/SensorParentKeySerializer.java b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/SensorParentKeySerializer.java
similarity index 94%
rename from theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/util/SensorParentKeySerializer.java
rename to theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/SensorParentKeySerializer.java
index bdd403a05de8f54f636568e839f5f48effd43d58..c18709436eec4f34113d0737821a9fab319ee9c1 100644
--- a/theodolite-benchmarks/uc4-flink/src/main/java/theodolite/uc4/application/util/SensorParentKeySerializer.java
+++ b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/SensorParentKeySerializer.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.application.util;
+package rocks.theodolite.benchmarks.uc4.flink.util;
 
 import com.esotericsoftware.kryo.Kryo;
 import com.esotericsoftware.kryo.Serializer;
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc4-hazelcastjet/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,286 @@
+cleanup.add_all=false
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
+cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
+cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
+sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc4-hazelcastjet/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=false
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc4-hazelcastjet/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=false
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/Dockerfile b/theodolite-benchmarks/uc4-hazelcastjet/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..a09c59d007a4de426a5046221662cdf1e912ee56
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/Dockerfile
@@ -0,0 +1,7 @@
+FROM openjdk:11-slim
+
+ADD build/distributions/uc4-hazelcastjet.tar /
+
+
+CMD  JAVA_OPTS="$JAVA_OPTS -Dorg.slf4j.simpleLogger.defaultLogLevel=$LOG_LEVEL" \
+     /uc4-hazelcastjet/bin/uc4-hazelcastjet
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/build.gradle b/theodolite-benchmarks/uc4-hazelcastjet/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..01daa0b88ffea88ed52e1ca6afa682150ade1b50
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/build.gradle
@@ -0,0 +1,5 @@
+plugins {
+  id 'theodolite.hazelcastjet'
+}
+
+mainClassName = "rocks.theodolite.benchmarks.uc4.hazelcastjet.HistoryService"
\ No newline at end of file
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/HistoryService.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/HistoryService.java
new file mode 100644
index 0000000000000000000000000000000000000000..419c25fec3eeffbd9eabef4897c44b7c6e773cee
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/HistoryService.java
@@ -0,0 +1,74 @@
+package rocks.theodolite.benchmarks.uc4.hazelcastjet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A microservice that manages the history and, therefore, stores and aggregates incoming
+ * measurements.
+ */
+public class HistoryService {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(HistoryService.class);
+
+  // Hazelcast settings (default)
+  private static final String HZ_KUBERNETES_SERVICE_DNS_KEY = "service-dns";
+  private static final String BOOTSTRAP_SERVER_DEFAULT = "localhost:5701";
+
+  // Kafka settings (default)
+  private static final String KAFKA_BOOTSTRAP_DEFAULT = "localhost:9092";
+  private static final String SCHEMA_REGISTRY_URL_DEFAULT = "http://localhost:8081";
+  private static final String KAFKA_INPUT_TOPIC_DEFAULT = "input";
+  private static final String KAFKA_CONFIG_TOPIC_DEFAULT = "configuration";
+  private static final String KAFKA_FEEDBACK_TOPIC_DEFAULT = "aggregation-feedback";
+  private static final String KAFKA_OUTPUT_TOPIC_DEFAULT = "output";
+
+  // UC4 specific (default)
+  private static final String WINDOW_SIZE_DEFAULT_MS = "5000";
+
+  // Job name (default)
+  private static final String JOB_NAME = "uc4-hazelcastjet";
+
+  /**
+   * Entrypoint for UC4 using Gradle Run.
+   */
+  public static void main(final String[] args) {
+    final HistoryService uc4HistoryService = new HistoryService();
+    try {
+      uc4HistoryService.run();
+    } catch (final Exception e) { // NOPMD
+      LOGGER.error("ABORT MISSION!: {}", e);
+    }
+  }
+
+  /**
+   * Start a UC4 service.
+   *
+   * @throws Exception This Exception occurs if the Uc4HazelcastJetFactory is used in the wrong way.
+   *         Detailed data is provided once an Exception occurs.
+   */
+  public void run() throws Exception { // NOPMD
+    this.createHazelcastJetApplication();
+  }
+
+  /**
+   * Creates a Hazelcast Jet Application for UC4 using the Uc1HazelcastJetFactory.
+   *
+   * @throws Exception This Exception occurs if the Uc4HazelcastJetFactory is used in the wrong way.
+   *         Detailed data is provided once an Exception occurs.
+   */
+  private void createHazelcastJetApplication() throws Exception { // NOPMD
+    new Uc4HazelcastJetFactory()
+        .setReadPropertiesFromEnv(KAFKA_BOOTSTRAP_DEFAULT, SCHEMA_REGISTRY_URL_DEFAULT,JOB_NAME)
+        .setWritePropertiesFromEnv(KAFKA_BOOTSTRAP_DEFAULT, SCHEMA_REGISTRY_URL_DEFAULT)
+        .setKafkaInputTopicFromEnv(KAFKA_INPUT_TOPIC_DEFAULT)
+        .setKafkaOutputTopicFromEnv(KAFKA_OUTPUT_TOPIC_DEFAULT)
+        .setKafkaConfigurationTopicFromEnv(KAFKA_CONFIG_TOPIC_DEFAULT)
+        .setKafkaFeedbackTopicFromEnv(KAFKA_FEEDBACK_TOPIC_DEFAULT)
+        .setWindowSizeFromEnv(WINDOW_SIZE_DEFAULT_MS)
+        .buildUc4JetInstanceFromEnv(LOGGER, BOOTSTRAP_SERVER_DEFAULT, HZ_KUBERNETES_SERVICE_DNS_KEY)
+        .buildUc4Pipeline()
+        .runUc4Job(JOB_NAME);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4HazelcastJetFactory.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4HazelcastJetFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..9b6aa71267150296d8b65268b1922925b7ada796
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4HazelcastJetFactory.java
@@ -0,0 +1,389 @@
+package rocks.theodolite.benchmarks.uc4.hazelcastjet;
+
+import com.hazelcast.jet.JetInstance;
+import com.hazelcast.jet.config.JobConfig;
+import com.hazelcast.jet.pipeline.Pipeline;
+import io.confluent.kafka.serializers.KafkaAvroDeserializer;
+import io.confluent.kafka.serializers.KafkaAvroSerializer;
+import java.util.Objects;
+import java.util.Properties;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import org.apache.kafka.common.serialization.StringSerializer;
+import org.slf4j.Logger;
+import rocks.theodolite.benchmarks.commons.hazelcastjet.ConfigurationKeys;
+import rocks.theodolite.benchmarks.commons.hazelcastjet.JetInstanceBuilder;
+import rocks.theodolite.benchmarks.commons.hazelcastjet.KafkaPropertiesBuilder;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.EventDeserializer;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ImmutableSensorRegistryUc4Serializer;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.SensorGroupKey;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.SensorGroupKeySerializer;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ValueGroup;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ValueGroupSerializer;
+import titan.ccp.model.sensorregistry.ImmutableSensorRegistry;
+
+/**
+ * A Hazelcast Jet factory which can build a Hazelcast Jet Instance and Pipeline for the UC4
+ * benchmark and lets you start the Hazelcast Jet job. The JetInstance can be built directly as the
+ * Hazelcast Config is managed internally. In order to build the Pipeline, you first have to build
+ * the Read and Write Properties and set the input, output, and configuration topic. This can be
+ * done using internal functions of this factory. Outside data only refers to custom values or
+ * default values in case data of the environment cannot the fetched.
+ */
+public class Uc4HazelcastJetFactory {
+
+  // Information per History Service
+  private Properties kafkaInputReadPropsForPipeline;
+  private Properties kafkaConfigPropsForPipeline;
+  private Properties kafkaFeedbackPropsForPipeline;
+  private Properties kafkaWritePropsForPipeline;
+  private String kafkaInputTopic;
+  private String kafkaOutputTopic;
+  private JetInstance uc4JetInstance;
+  private Pipeline uc4JetPipeline;
+  // UC4 specific
+  private String kafkaConfigurationTopic;
+  private String kafkaFeedbackTopic;
+  private int windowSize;
+
+  /////////////////////////////////////
+  // Layer 1 - Hazelcast Jet Run Job //
+  /////////////////////////////////////
+
+  /**
+   * Needs a JetInstance and Pipeline defined in this factors. Adds the pipeline to the existing
+   * JetInstance as a job.
+   *
+   * @param jobName The name of the job.
+   * @throws Exception If either no JetInstance or Pipeline is set, a job cannot be startet.
+   */
+  public void runUc4Job(final String jobName) throws IllegalStateException { // NOPMD
+
+    // Check if a Jet Instance for UC4 is set.
+    if (this.uc4JetInstance == null) {
+      throw new IllegalStateException("Jet Instance is not set! "
+          + "Cannot start a hazelcast jet job for UC4.");
+    }
+
+    // Check if a Pipeline for UC3 is set.
+    if (this.uc4JetPipeline == null) {
+      throw new IllegalStateException(
+          "Hazelcast Pipeline is not set! Cannot start a hazelcast jet job for UC4.");
+    }
+
+    // Adds the job name and joins a job to the JetInstance defined in this factory
+    final JobConfig jobConfig = new JobConfig()
+        .registerSerializer(ValueGroup.class, ValueGroupSerializer.class)
+        .registerSerializer(SensorGroupKey.class, SensorGroupKeySerializer.class)
+        .registerSerializer(ImmutableSensorRegistry.class,
+            ImmutableSensorRegistryUc4Serializer.class)
+        .setName(jobName);
+    this.uc4JetInstance.newJobIfAbsent(this.uc4JetPipeline, jobConfig).join();
+  }
+
+  /////////////
+  // Layer 2 //
+  /////////////
+
+  /**
+   * Build a Hazelcast JetInstance used to run a job on.
+   *
+   * @param logger The logger specified for this JetInstance.
+   * @param bootstrapServerDefault Default bootstrap server in case no value can be derived from the
+   *        environment.
+   * @param hzKubernetesServiceDnsKey The kubernetes service dns key.
+   * @return A Uc4HazelcastJetFactory containing a set JetInstance.
+   */
+  public Uc4HazelcastJetFactory buildUc4JetInstanceFromEnv(final Logger logger,
+      final String bootstrapServerDefault,
+      final String hzKubernetesServiceDnsKey) {
+    this.uc4JetInstance = new JetInstanceBuilder()
+        .setConfigFromEnv(logger, bootstrapServerDefault, hzKubernetesServiceDnsKey)
+        .build();
+    return this;
+  }
+
+  /**
+   * Builds a Hazelcast Jet pipeline used for a JetInstance to run it as a job on. Needs the input
+   * topic and kafka properties defined in this factory beforehand.
+   *
+   * @return A Uc4HazelcastJetFactory containg a set pipeline.
+   * @throws Exception If the input topic or the kafka properties are not defined, the pipeline
+   *         cannot be built.
+   */
+  public Uc4HazelcastJetFactory buildUc4Pipeline() throws IllegalStateException { // NOPMD
+
+    final String defaultPipelineWarning = "Cannot build pipeline."; // NOPMD
+
+    // Check if Properties for the Kafka Input are set.
+    if (this.kafkaInputReadPropsForPipeline == null) {
+      throw new IllegalStateException("Kafka Input Read Properties for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if Properties for the Kafka Output are set.
+    if (this.kafkaWritePropsForPipeline == null) {
+      throw new IllegalStateException("Kafka Write Properties for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if Properties for the Kafka Config Read are set.
+    if (this.kafkaConfigPropsForPipeline == null) {
+      throw new IllegalStateException("Kafka Config Read Properties for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if Properties for the Kafka Feedback Read are set.
+    if (this.kafkaFeedbackPropsForPipeline == null) {
+      throw new IllegalStateException("Kafka Feedback Read Properties for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if the Kafka input topic is set.
+    if (this.kafkaInputTopic == null) {
+      throw new IllegalStateException("Kafka input topic for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if the Kafka output topic is set.
+    if (this.kafkaOutputTopic == null) {
+      throw new IllegalStateException("kafka output topic for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if the Kafka config topic is set.
+    if (this.kafkaConfigurationTopic == null) {
+      throw new IllegalStateException("configuratin topic for pipeline not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if the Kafka feedback topic is set.
+    if (this.kafkaFeedbackTopic == null) {
+      throw new IllegalStateException("Feedback topic not set! "
+          + defaultPipelineWarning);
+    }
+
+    // Check if window size for tumbling window is set.
+    if (this.windowSize <= 0) {
+      throw new IllegalStateException("window size for pipeline not set or not greater than 0! "
+          + defaultPipelineWarning);
+    }
+
+    // Build Pipeline Using the pipelineBuilder
+    final Uc4PipelineBuilder pipeBuilder = new Uc4PipelineBuilder();
+    this.uc4JetPipeline =
+        pipeBuilder.build(this.kafkaInputReadPropsForPipeline,
+            this.kafkaConfigPropsForPipeline,
+            this.kafkaFeedbackPropsForPipeline,
+            this.kafkaWritePropsForPipeline,
+            this.kafkaInputTopic, this.kafkaOutputTopic,
+            this.kafkaConfigurationTopic,
+            this.kafkaFeedbackTopic,
+            this.windowSize);
+    // Return Uc4HazelcastJetBuilder factory
+    return this;
+  }
+
+  /////////////
+  // Layer 3 //
+  /////////////
+
+  /**
+   * Sets kafka read properties for pipeline used in this builder using environment variables.
+   *
+   * @param bootstrapServersDefault Default Bootstrap server in the case that no bootstrap server
+   *        can be fetched from the environment.
+   * @param schemaRegistryUrlDefault Default schema registry url in the case that no schema registry
+   *        url can be fetched from the environment.
+   * @return The Uc4HazelcastJetBuilder factory with set kafkaReadPropertiesForPipeline.
+   */
+  public Uc4HazelcastJetFactory setReadPropertiesFromEnv(// NOPMD
+                                                         final String bootstrapServersDefault,
+                                                         final String schemaRegistryUrlDefault,
+                                                         final String jobName) {
+    // Use KafkaPropertiesBuilder to build a properties object used for kafka
+    final KafkaPropertiesBuilder propsBuilder = new KafkaPropertiesBuilder();
+
+    final Properties kafkaInputReadProps =
+        propsBuilder.buildKafkaInputReadPropsFromEnv(bootstrapServersDefault,
+            schemaRegistryUrlDefault, jobName,
+            StringDeserializer.class.getCanonicalName(),
+            KafkaAvroDeserializer.class.getCanonicalName());
+
+    final Properties kafkaConfigReadProps =
+        propsBuilder.buildKafkaInputReadPropsFromEnv(bootstrapServersDefault,
+            schemaRegistryUrlDefault,
+            jobName,
+            EventDeserializer.class.getCanonicalName(),
+            StringDeserializer.class.getCanonicalName());
+
+    final Properties kafkaAggregationReadProps =
+        propsBuilder.buildKafkaInputReadPropsFromEnv(bootstrapServersDefault,
+            schemaRegistryUrlDefault,
+            jobName,
+            StringDeserializer.class.getCanonicalName(),
+            KafkaAvroDeserializer.class.getCanonicalName());
+
+    this.kafkaInputReadPropsForPipeline = kafkaInputReadProps;
+    this.kafkaConfigPropsForPipeline = kafkaConfigReadProps;
+    this.kafkaFeedbackPropsForPipeline = kafkaAggregationReadProps;
+    return this;
+  }
+
+  /**
+   * Sets kafka write properties for pipeline used in this builder using environment variables.
+   *
+   * @param bootstrapServersDefault Default Bootstrap server in the case that no bootstrap server
+   *        can be fetched from the environment.
+   * @return The Uc4HazelcastJetBuilder factory with set kafkaWritePropertiesForPipeline.
+   */
+  public Uc4HazelcastJetFactory setWritePropertiesFromEnv(// NOPMD
+      final String bootstrapServersDefault, final String schemaRegistryUrlDefault) {
+    // Use KafkaPropertiesBuilder to build a properties object used for kafka
+    final KafkaPropertiesBuilder propsBuilder = new KafkaPropertiesBuilder();
+    final Properties kafkaWriteProps =
+        propsBuilder.buildKafkaWritePropsFromEnv(bootstrapServersDefault,
+            schemaRegistryUrlDefault,
+            StringSerializer.class.getCanonicalName(),
+            KafkaAvroSerializer.class.getCanonicalName());
+    this.kafkaWritePropsForPipeline = kafkaWriteProps;
+    return this;
+  }
+
+  /**
+   * Sets the kafka input topic for the pipeline used in this builder.
+   *
+   * @param inputTopic The kafka topic used as the pipeline input.
+   * @return A Uc4HazelcastJetBuilder factory with a set kafkaInputTopic.
+   */
+  public Uc4HazelcastJetFactory setCustomKafkaInputTopic(// NOPMD
+      final String inputTopic) {
+    this.kafkaInputTopic = inputTopic;
+    return this;
+  }
+
+  /**
+   * Sets the kafka input output for the pipeline used in this builder.
+   *
+   * @param outputTopic The kafka topic used as the pipeline output.
+   * @return A Uc4HazelcastJetBuilder factory with a set kafkaOutputTopic.
+   */
+  public Uc4HazelcastJetFactory setCustomKafkaOutputTopic(final String outputTopic) { // NOPMD
+    this.kafkaOutputTopic = outputTopic;
+    return this;
+  }
+
+
+  /**
+   * Sets the kafka input topic for the pipeline used in this builder using environment variables.
+   *
+   * @param defaultInputTopic The default kafka input topic used if no topic is specified by the
+   *        environment.
+   * @return A Uc4HazelcastJetBuilder factory with a set kafkaInputTopic.
+   */
+  public Uc4HazelcastJetFactory setKafkaInputTopicFromEnv(// NOPMD
+      final String defaultInputTopic) {
+    this.kafkaInputTopic = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_INPUT_TOPIC),
+        defaultInputTopic);
+    return this;
+  }
+
+  /**
+   * Sets the kafka output topic for the pipeline used in this builder using environment variables.
+   *
+   * @param defaultOutputTopic The default kafka output topic used if no topic is specified by the
+   *        environment.
+   * @return A Uc4HazelcastJetBuilder factory with a set kafkaOutputTopic.
+   */
+  public Uc4HazelcastJetFactory setKafkaOutputTopicFromEnv(// NOPMD
+      final String defaultOutputTopic) {
+    this.kafkaOutputTopic = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_OUTPUT_TOPIC),
+        defaultOutputTopic);
+    return this;
+  }
+
+  /**
+   * Sets the window size for the pipeline used in this builder.
+   *
+   * @param windowSize the window size to be used for this pipeline.
+   * @return A Uc4HazelcastJetFactory with a set windowSize.
+   */
+  public Uc4HazelcastJetFactory setCustomWindowSize(// NOPMD
+      final int windowSize) {
+    this.windowSize = windowSize;
+    return this;
+  }
+
+  /**
+   * Sets the window size for the pipeline used in this builder from the environment.
+   *
+   * @param defaultWindowSize the default window size to be used for this pipeline when none is set
+   *        in the environment.
+   * @return A Uc4HazelcastJetFactory with a set windowSize.
+   */
+  public Uc4HazelcastJetFactory setWindowSizeFromEnv(// NOPMD
+      final String defaultWindowSize) {
+    final String windowSize = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.WINDOW_SIZE_UC4),
+        defaultWindowSize);
+    final int windowSizeNumber = Integer.parseInt(windowSize);
+    this.windowSize = windowSizeNumber;
+    return this;
+  }
+
+  /**
+   * Sets the configuration topic for the pipeline used in this builder.
+   *
+   * @param kafkaConfigurationTopic the configuration topic to be used for this pipeline.
+   * @return A Uc4HazelcastJetFactory with a set configuration topic.
+   */
+  public Uc4HazelcastJetFactory setCustomKafkaConfigurationTopic(// NOPMD
+      final String kafkaConfigurationTopic) {
+    this.kafkaConfigurationTopic = kafkaConfigurationTopic;
+    return this;
+  }
+
+  /**
+   * Sets the configuration topic for the pipeline used in this builder from the environment.
+   *
+   * @param defaultKafkaConfigurationTopic the default configuration topic to be used for this
+   *        pipeline when none is set in the environment.
+   * @return A Uc4HazelcastJetFactory with a set kafkaConfigurationTopic.
+   */
+  public Uc4HazelcastJetFactory setKafkaConfigurationTopicFromEnv(// NOPMD
+      final String defaultKafkaConfigurationTopic) {
+    this.kafkaConfigurationTopic = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_CONFIGURATION_TOPIC),
+        defaultKafkaConfigurationTopic);
+    return this;
+  }
+
+  /**
+   * Sets the Feedback topic for the pipeline used in this builder.
+   *
+   * @param kafkaFeedbackTopic the Feedback topic to be used for this pipeline.
+   * @return A Uc4HazelcastJetFactory with a set Feedback topic.
+   */
+  public Uc4HazelcastJetFactory setCustomKafkaFeedbackTopic(// NOPMD
+      final String kafkaFeedbackTopic) {
+    this.kafkaFeedbackTopic = kafkaFeedbackTopic;
+    return this;
+  }
+
+  /**
+   * Sets the Feedback topic for the pipeline used in this builder from the environment.
+   *
+   * @param defaultKafkaFeedbackTopic the default Feedback topic to be used for this pipeline when
+   *        none is set in the environment.
+   * @return A Uc4HazelcastJetFactory with a set kafkaFeedbackTopic.
+   */
+  public Uc4HazelcastJetFactory setKafkaFeedbackTopicFromEnv(// NOPMD
+      final String defaultKafkaFeedbackTopic) {
+    this.kafkaFeedbackTopic = Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_FEEDBACK_TOPIC),
+        defaultKafkaFeedbackTopic);
+    return this;
+  }
+
+}
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4PipelineBuilder.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4PipelineBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..2efb8250c0e1136b34412e4553b2d216c5e24b43
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4PipelineBuilder.java
@@ -0,0 +1,309 @@
+package rocks.theodolite.benchmarks.uc4.hazelcastjet;
+
+import com.hazelcast.function.BiFunctionEx;
+import com.hazelcast.jet.Traverser;
+import com.hazelcast.jet.Traversers;
+import com.hazelcast.jet.Util;
+import com.hazelcast.jet.aggregate.AggregateOperation;
+import com.hazelcast.jet.aggregate.AggregateOperation1;
+import com.hazelcast.jet.kafka.KafkaSinks;
+import com.hazelcast.jet.kafka.KafkaSources;
+import com.hazelcast.jet.pipeline.Pipeline;
+import com.hazelcast.jet.pipeline.Sinks;
+import com.hazelcast.jet.pipeline.StageWithWindow;
+import com.hazelcast.jet.pipeline.StreamSource;
+import com.hazelcast.jet.pipeline.StreamStage;
+import com.hazelcast.jet.pipeline.StreamStageWithKey;
+import com.hazelcast.jet.pipeline.WindowDefinition;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.AggregatedActivePowerRecordAccumulator;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ChildParentsTransformer;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.SensorGroupKey;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ValueGroup;
+import titan.ccp.configuration.events.Event;
+import titan.ccp.model.records.ActivePowerRecord;
+import titan.ccp.model.records.AggregatedActivePowerRecord;
+import titan.ccp.model.sensorregistry.SensorRegistry;
+
+/**
+ * Builder to build a HazelcastJet Pipeline for UC4 which can be used for stream processing using
+ * Hazelcast Jet.
+ */
+@SuppressWarnings("PMD.ExcessiveImports")
+public class Uc4PipelineBuilder {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(Uc4PipelineBuilder.class);
+  private static final String SENSOR_PARENT_MAP_NAME = "SensorParentMap";
+
+  /**
+   * Builds a pipeline which can be used for stream processing using Hazelcast Jet.
+   *
+   * @param kafkaInputReadPropsForPipeline Properties Object containing the necessary kafka input
+   *        read attributes.
+   * @param kafkaConfigPropsForPipeline Properties Object containing the necessary kafka config read
+   *        attributes.
+   * @param kafkaFeedbackPropsForPipeline Properties Object containing the necessary kafka
+   *        aggregation read attributes.
+   * @param kafkaWritePropsForPipeline Properties Object containing the necessary kafka write
+   *        attributes.
+   * @param kafkaInputTopic The name of the input topic used for the pipeline.
+   * @param kafkaOutputTopic The name of the output topic used for the pipeline.
+   * @param kafkaConfigurationTopic The name of the configuration topic used for the pipeline.
+   * @param kafkaFeedbackTopic The name of the feedback topic used for the pipeline.
+   * @param windowSize The window size of the tumbling window used in this pipeline.
+   * @return returns a Pipeline used which can be used in a Hazelcast Jet Instance to process data
+   *         for UC3.
+   */
+  public Pipeline build(final Properties kafkaInputReadPropsForPipeline, // NOPMD
+      final Properties kafkaConfigPropsForPipeline,
+      final Properties kafkaFeedbackPropsForPipeline,
+      final Properties kafkaWritePropsForPipeline,
+      final String kafkaInputTopic,
+      final String kafkaOutputTopic,
+      final String kafkaConfigurationTopic,
+      final String kafkaFeedbackTopic,
+      final int windowSize) {
+
+    if (LOGGER.isInfoEnabled()) {
+      LOGGER.info("kafkaConfigProps: " + kafkaConfigPropsForPipeline);
+      LOGGER.info("kafkaFeedbackProps: " + kafkaFeedbackPropsForPipeline);
+      LOGGER.info("kafkaWriteProps: " + kafkaWritePropsForPipeline);
+    }
+
+    // The pipeline for this Use Case
+    final Pipeline uc4Pipeline = Pipeline.create();
+
+    // Sources for this use case
+    final StreamSource<Entry<Event, String>> configSource =
+        KafkaSources.kafka(kafkaConfigPropsForPipeline, kafkaConfigurationTopic);
+
+    final StreamSource<Entry<String, ActivePowerRecord>> inputSource =
+        KafkaSources.kafka(kafkaInputReadPropsForPipeline, kafkaInputTopic);
+
+    final StreamSource<Entry<String, AggregatedActivePowerRecord>> aggregationSource =
+        KafkaSources.kafka(kafkaFeedbackPropsForPipeline, kafkaFeedbackTopic);
+
+    // Extend UC4 topology to pipeline
+    final StreamStage<Entry<String, AggregatedActivePowerRecord>> uc4Aggregation =
+        this.extendUc4Topology(uc4Pipeline, inputSource, aggregationSource, configSource,
+            windowSize);
+
+    // Add Sink2: Write back to kafka feedback/aggregation topic
+    uc4Aggregation.writeTo(KafkaSinks.kafka(
+        kafkaWritePropsForPipeline, kafkaFeedbackTopic));
+
+    // Log aggregation product
+    uc4Aggregation.writeTo(Sinks.logger());
+
+    // Add Sink2: Write back to kafka output topic
+    uc4Aggregation.writeTo(KafkaSinks.kafka(
+        kafkaWritePropsForPipeline, kafkaOutputTopic));
+
+    // Return the pipeline
+    return uc4Pipeline;
+  }
+
+  /**
+   * Extends to a blank Hazelcast Jet Pipeline the UC4 topology defines by theodolite.
+   *
+   * <p>
+   * UC4 takes {@code ActivePowerRecord} events from sensors and a {@code SensorRegistry} with maps
+   * from keys to groups to map values to their according groups. A feedback stream allows for
+   * group keys to be mapped to values and eventually to be mapped to other top level groups defines
+   * by the {@code SensorRegistry}.
+   * </p>
+   *
+   * <p>
+   * 6 Step topology: <br>
+   * (1) Inputs (Config, Values, Aggregations) <br>
+   * (2) Merge Input Values and Aggregations <br>
+   * (3) Join Configuration with Merged Input Stream <br>
+   * (4) Duplicate as flatmap per value and group <br>
+   * (5) Window (preparation for possible last values) <br>
+   * (6) Aggregate data over the window
+   * </p>
+   *
+   * @param pipe The blank pipeline to extend the logic to.
+   * @param inputSource A streaming source with {@code ActivePowerRecord} data.
+   * @param aggregationSource A streaming source with aggregated data.
+   * @param configurationSource A streaming source delivering a {@code SensorRegistry}.
+   * @param windowSize The window size used to aggregate over.
+   * @return A {@code StreamSource<String,Double>} with sensorKeys or groupKeys mapped to their
+   *         according aggregated values. The data can be further modified or directly be linked to
+   *         a Hazelcast Jet sink.
+   */
+  public StreamStage<Entry<String, AggregatedActivePowerRecord>> extendUc4Topology(// NOPMD
+      final Pipeline pipe,
+      final StreamSource<Entry<String, ActivePowerRecord>> inputSource,
+      final StreamSource<Entry<String, AggregatedActivePowerRecord>> aggregationSource,
+      final StreamSource<Entry<Event, String>> configurationSource, final int windowSize) {
+
+    //////////////////////////////////
+    // (1) Configuration Stream
+    pipe.readFrom(configurationSource)
+        .withNativeTimestamps(0)
+        .filter(entry -> entry.getKey() == Event.SENSOR_REGISTRY_CHANGED
+            || entry.getKey() == Event.SENSOR_REGISTRY_STATUS)
+        .map(data -> Util.entry(data.getKey(), SensorRegistry.fromJson(data.getValue())))
+        .flatMapStateful(HashMap::new, new ConfigFlatMap())
+        .writeTo(Sinks.mapWithUpdating(
+            SENSOR_PARENT_MAP_NAME, // The addressed IMAP
+            Entry::getKey, // The key to look for
+            (oldValue, newEntry) -> newEntry.getValue()));
+
+    //////////////////////////////////
+    // (1) Sensor Input Stream
+    final StreamStage<Entry<String, ActivePowerRecord>> inputStream = pipe
+        .readFrom(inputSource)
+        .withNativeTimestamps(0);
+
+    //////////////////////////////////
+    // (1) Aggregation Stream
+    final StreamStage<Entry<String, ActivePowerRecord>> aggregations = pipe
+        .readFrom(aggregationSource)
+        .withNativeTimestamps(0)
+        .map(entry -> { // Map Aggregated to ActivePowerRecord
+          final AggregatedActivePowerRecord agg = entry.getValue();
+          final ActivePowerRecord record = new ActivePowerRecord(
+              agg.getIdentifier(), agg.getTimestamp(), agg.getSumInW());
+          return Util.entry(entry.getKey(), record);
+        });
+
+    //////////////////////////////////
+    // (2) UC4 Merge Input with aggregation stream
+    final StreamStageWithKey<Entry<String, ActivePowerRecord>, String>
+        mergedInputAndAggregations = inputStream
+        .merge(aggregations)
+        .groupingKey(Entry::getKey);
+
+    //////////////////////////////////
+    // (3) UC4 Join Configuration and Merges Input/Aggregation Stream
+    // [sensorKey , (value,Set<Groups>)]
+    final StreamStage<Entry<String, ValueGroup>> joinedStage = mergedInputAndAggregations
+        .<Set<String>, Entry<String, ValueGroup>>mapUsingIMap(
+            SENSOR_PARENT_MAP_NAME,
+            (sensorEvent, sensorParentsSet) -> {
+              // Check whether a groupset exists for a key or not
+              if (sensorParentsSet == null) {
+                // No group set exists for this key: return valuegroup with default null group set.
+                final Set<String> nullSet = new HashSet<>();
+                nullSet.add("NULL-GROUPSET");
+                return Util.entry(sensorEvent.getKey(),
+                    new ValueGroup(sensorEvent.getValue(), nullSet));
+              } else {
+                // Group set exists for this key: return valuegroup with the groupset.
+                final ValueGroup valueParentsPair =
+                    new ValueGroup(sensorEvent.getValue(), sensorParentsSet);
+                // Return solution
+                return Util.entry(sensorEvent.getKey(), valueParentsPair);
+              }
+            });
+
+    //////////////////////////////////
+    // (4) UC4 Duplicate as flatmap joined Stream
+    // [(sensorKey, Group) , value]
+    final StreamStage<Entry<SensorGroupKey, ActivePowerRecord>> dupliAsFlatmappedStage = joinedStage
+        .flatMap(entry -> {
+
+          // Supplied data
+          final String keyGroupId = entry.getKey();
+          final ActivePowerRecord record = entry.getValue().getRecord();
+          final Set<String> groups = entry.getValue().getGroups();
+
+          // Transformed Data
+          final String[] groupList = groups.toArray(String[]::new);
+          final SensorGroupKey[] newKeyList = new SensorGroupKey[groupList.length];
+          final List<Entry<SensorGroupKey, ActivePowerRecord>> newEntryList = new ArrayList<>();
+          for (int i = 0; i < groupList.length; i++) {
+            newKeyList[i] = new SensorGroupKey(keyGroupId, groupList[i]);
+            newEntryList.add(Util.entry(newKeyList[i], record));
+          }
+
+          // Return traversable list of new entry elements
+          return Traversers.traverseIterable(newEntryList);
+        });
+
+    //////////////////////////////////
+    // (5) UC4 Last Value Map
+    // Table with tumbling window differentiation [ (sensorKey,Group) , value ],Time
+    final StageWithWindow<Entry<SensorGroupKey, ActivePowerRecord>>
+        windowedLastValues = dupliAsFlatmappedStage
+        .window(WindowDefinition.tumbling(windowSize));
+
+    final AggregateOperation1<Entry<SensorGroupKey, ActivePowerRecord>,
+        AggregatedActivePowerRecordAccumulator, AggregatedActivePowerRecord> aggrOp =
+        AggregateOperation
+        .withCreate(AggregatedActivePowerRecordAccumulator::new)
+        .<Entry<SensorGroupKey, ActivePowerRecord>>andAccumulate((acc, rec) -> {
+          acc.setId(rec.getKey().getGroup());
+          acc.addInputs(rec.getValue());
+        })
+        .andCombine((acc, acc2) ->
+            acc.addInputs(acc2.getId(), acc2.getSumInW(), acc2.getCount(), acc.getTimestamp()))
+        .andDeduct((acc, acc2) -> acc.removeInputs(acc2.getSumInW(), acc2.getCount()))
+        .andExportFinish(acc ->
+            new AggregatedActivePowerRecord(acc.getId(),
+                acc.getTimestamp(),
+                acc.getCount(),
+                acc.getSumInW(),
+                acc.getAverageInW())
+        );
+
+    // write aggregation back to kafka
+
+    return windowedLastValues
+        .groupingKey(entry -> entry.getKey().getGroup())
+        .aggregate(aggrOp).map(agg -> Util.entry(agg.getKey(), agg.getValue()));
+  }
+
+
+
+  /**
+   * FlatMap function used to process the configuration input for UC4.
+   */
+  private static class ConfigFlatMap implements
+      BiFunctionEx<Map<String, Set<String>>, Entry<Event, SensorRegistry>, Traverser<Entry<String, Set<String>>>> { // NOCS
+
+    private static final long serialVersionUID = -6769931374907428699L;
+
+    @Override
+    public Traverser<Entry<String, Set<String>>> applyEx(
+        final Map<String, Set<String>> flatMapStage,
+        final Entry<Event, SensorRegistry> eventItem) {
+      // Transform new Input
+      final ChildParentsTransformer transformer = new ChildParentsTransformer("default-name");
+      final Map<String, Set<String>> mapFromRegistry =
+          transformer.constructChildParentsPairs(eventItem.getValue());
+
+      // Compare both tables
+      final Map<String, Set<String>> updates = new HashMap<>();
+      for (final String key : mapFromRegistry.keySet()) {
+        if (flatMapStage.containsKey(key)) {
+          if (!mapFromRegistry.get(key).equals(flatMapStage.get(key))) {
+            updates.put(key, mapFromRegistry.get(key));
+          }
+        } else {
+          updates.put(key, mapFromRegistry.get(key));
+        }
+      }
+
+      // Create a updates list to pass onto the next pipeline stage-
+      final List<Entry<String, Set<String>>> updatesList = new ArrayList<>(updates.entrySet());
+
+      // Return traverser with updates list.
+      return Traversers.traverseIterable(updatesList)
+          .map(e -> Util.entry(e.getKey(), e.getValue()));
+    }
+
+  }
+
+}
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/AggregatedActivePowerRecordAccumulator.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/AggregatedActivePowerRecordAccumulator.java
new file mode 100644
index 0000000000000000000000000000000000000000..3166f16cd31bf0e6d4dff6548468791e7a5e5c5c
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/AggregatedActivePowerRecordAccumulator.java
@@ -0,0 +1,100 @@
+package rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics;
+
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * Accumulator class for AggregatedActivePowerRecords.
+ */
+public class AggregatedActivePowerRecordAccumulator {
+
+  private String id;
+  private long timestamp;
+  private long count;
+  private double sumInW;
+  private double averageInW;
+
+  /**
+   * Default constructor.
+   */
+  public AggregatedActivePowerRecordAccumulator() {
+    // This constructor is intentionally empty. Nothing special is needed here.
+  }
+
+
+  /**
+   * Creates an AggregationObject.
+   */
+  public AggregatedActivePowerRecordAccumulator(final String id,
+                                                final long timestamp,
+                                                final long count,
+                                                final double sumInW,
+                                                final double averageInW) {
+    this.id = id;
+    this.timestamp = timestamp;
+    this.count = count;
+    this.sumInW = sumInW;
+    this.averageInW = averageInW;
+  }
+
+  /**
+   * Sets the id.
+   */
+  public void setId(final String id) {
+    this.id = id;
+  }
+
+  /**
+   * Adds the record to the aggregation.
+   */
+  public void addInputs(final ActivePowerRecord record) {
+    this.count += 1;
+    this.sumInW += record.getValueInW();
+    this.timestamp = record.getTimestamp();
+    this.averageInW = sumInW / count;
+  }
+
+  /**
+   * Adds the records from another aggregator.
+   */
+  public void addInputs(final String id,
+                        final double sumInW,
+                        final long count,
+                        final long timestamp) {
+    this.id = this.id == null ? id : this.id;
+    this.sumInW += sumInW;
+    this.count += count;
+    this.timestamp = Math.max(this.timestamp, timestamp);
+    this.averageInW = this.sumInW / this.count;
+  }
+
+  /**
+   * Removes the values of another aggreagator.
+   * Not a complete reset since the old timestamp is lost.
+   */
+  public void removeInputs(final double sumInW, final long count) {
+    this.sumInW -= sumInW;
+    this.count -= count;
+    this.averageInW = this.count == 0 ? 0.0 : this.sumInW / this.count;
+    this.timestamp = -1L;
+  }
+
+  public long getCount() {
+    return count;
+  }
+
+  public double getSumInW() {
+    return sumInW;
+  }
+
+  public double getAverageInW() {
+    return averageInW;
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  public long getTimestamp() {
+    return timestamp;
+  }
+}
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ChildParentsTransformer.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ChildParentsTransformer.java
new file mode 100644
index 0000000000000000000000000000000000000000..ad3b2294cb934ba04b07df2e2b2d3dbdd6e1a905
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ChildParentsTransformer.java
@@ -0,0 +1,118 @@
+package rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.kafka.streams.KeyValue;
+import org.apache.kafka.streams.kstream.Transformer;
+import org.apache.kafka.streams.processor.ProcessorContext;
+import org.apache.kafka.streams.state.KeyValueIterator;
+import org.apache.kafka.streams.state.KeyValueStore;
+import titan.ccp.configuration.events.Event;
+import titan.ccp.model.sensorregistry.AggregatedSensor;
+import titan.ccp.model.sensorregistry.Sensor;
+import titan.ccp.model.sensorregistry.SensorRegistry;
+
+/**
+ * Transforms a {@link SensorRegistry} into key value pairs of Sensor identifiers and their parents'
+ * sensor identifiers. All pairs whose sensor's parents have changed since last iteration are
+ * forwarded. A mapping of an identifier to <code>null</code> means that the corresponding sensor
+ * does not longer exists in the sensor registry.
+ *
+ */
+public class ChildParentsTransformer implements
+    Transformer<Event, SensorRegistry, Iterable<KeyValue<String, Optional<Set<String>>>>> {
+
+  private final String stateStoreName;
+  // private ProcessorContext context;
+  private KeyValueStore<String, Set<String>> state;
+
+  public ChildParentsTransformer(final String stateStoreName) {
+    this.stateStoreName = stateStoreName;
+  }
+
+  @Override
+  @SuppressWarnings("unchecked")
+  public void init(final ProcessorContext context) {
+    // this.context = context;
+    this.state = (KeyValueStore<String, Set<String>>) context.getStateStore(this.stateStoreName);
+  }
+
+  @Override
+  public Iterable<KeyValue<String, Optional<Set<String>>>> transform(final Event event,
+      final SensorRegistry registry) {
+
+    // Values may later be null for deleting a sensor
+    final Map<String, Set<String>> childParentsPairs = this.constructChildParentsPairs(registry);
+
+    this.updateChildParentsPairs(childParentsPairs);
+
+    this.updateState(childParentsPairs);
+
+    return childParentsPairs
+        .entrySet()
+        .stream()
+        .map(e -> KeyValue.pair(e.getKey(), Optional.ofNullable(e.getValue())))
+        .collect(Collectors.toList());
+  }
+
+  @Override
+  public void close() {
+    // Do nothing
+  }
+
+  /**
+   * Constructs a map of keys to their set of parents out of a SensorRegistry.
+   *
+   * @param registry The SensorRegistry to build the map out of.
+   * @return A map of keys to a set of their parents.
+   */
+  public Map<String, Set<String>> constructChildParentsPairs(final SensorRegistry registry) {
+    return this.streamAllChildren(registry.getTopLevelSensor())
+        .collect(Collectors.toMap(
+            Sensor::getIdentifier,
+            child -> child.getParent()
+                .map(p -> Set.of(p.getIdentifier()))
+                .orElseGet(Set::of)));
+  }
+
+  private Stream<Sensor> streamAllChildren(final AggregatedSensor sensor) {
+    return sensor.getChildren().stream()
+        .flatMap(s -> Stream.concat(
+            Stream.of(s),
+            s instanceof AggregatedSensor ? this.streamAllChildren((AggregatedSensor) s)
+                : Stream.empty()));
+  }
+
+  private void updateChildParentsPairs(final Map<String, Set<String>> childParentsPairs) {
+    final KeyValueIterator<String, Set<String>> oldChildParentsPairs = this.state.all();
+    while (oldChildParentsPairs.hasNext()) {
+      final KeyValue<String, Set<String>> oldChildParentPair = oldChildParentsPairs.next();
+      final String identifier = oldChildParentPair.key;
+      final Set<String> oldParents = oldChildParentPair.value;
+      final Set<String> newParents = childParentsPairs.get(identifier); // null if not exists
+      if (newParents == null) {
+        // Sensor was deleted
+        childParentsPairs.put(identifier, null);
+      } else if (newParents.equals(oldParents)) {
+        // No changes
+        childParentsPairs.remove(identifier);
+      }
+      // Else: Later Perhaps: Mark changed parents
+    }
+    oldChildParentsPairs.close();
+  }
+
+  private void updateState(final Map<String, Set<String>> childParentsPairs) {
+    for (final Map.Entry<String, Set<String>> childParentPair : childParentsPairs.entrySet()) {
+      if (childParentPair.getValue() == null) {
+        this.state.delete(childParentPair.getKey());
+      } else {
+        this.state.put(childParentPair.getKey(), childParentPair.getValue());
+      }
+    }
+  }
+
+}
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/EventDeserializer.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/EventDeserializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8d06b497009944b9a9a0fda4ab224e5fe992e3d
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/EventDeserializer.java
@@ -0,0 +1,32 @@
+package rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics;
+
+import java.util.Map;
+import org.apache.kafka.common.serialization.Deserializer;
+import titan.ccp.configuration.events.Event;
+import titan.ccp.configuration.events.EventSerde;
+
+/**
+ * Deserializer for Event Objects.
+ *
+ */
+public class EventDeserializer implements Deserializer<Event> {
+
+  private final Deserializer<Event> deserializer = EventSerde.serde().deserializer();
+
+  @Override
+  public void configure(final Map<String, ?> configs, final boolean isKey) {
+    this.deserializer.configure(configs, isKey);
+  }
+
+  @Override
+  public Event deserialize(final String topic, final byte[] data) {
+    return this.deserializer.deserialize(topic, data);
+  }
+
+  @Override
+  public void close() {
+    this.deserializer.close();
+  }
+
+
+}
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/HashMapSupplier.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/HashMapSupplier.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec240bf8cb925aa3a444b56457da5adc411212b2
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/HashMapSupplier.java
@@ -0,0 +1,26 @@
+package rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics;
+
+import com.hazelcast.function.SupplierEx;
+import java.util.HashMap;
+import java.util.Set;
+
+/**
+ * Supplies a {@link HashMap} and implements {@link SupplierEx}.
+ */
+public class HashMapSupplier implements SupplierEx<HashMap<String, Set<String>>> {
+
+  private static final long serialVersionUID = -6247504592403610702L; // NOPMD
+
+  @Override
+  public HashMap<String, Set<String>> get() {
+    return new HashMap<>();
+  }
+
+  @Override
+  public HashMap<String, Set<String>> getEx() throws Exception {
+    return this.get();
+  }
+
+
+
+}
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ImmutableSensorRegistryUc4Serializer.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ImmutableSensorRegistryUc4Serializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..53d22f7f156891cf11e5b8915eed17b74c3d57fb
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ImmutableSensorRegistryUc4Serializer.java
@@ -0,0 +1,36 @@
+package rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics;
+
+import com.hazelcast.nio.ObjectDataInput;
+import com.hazelcast.nio.ObjectDataOutput;
+import com.hazelcast.nio.serialization.StreamSerializer;
+import java.io.IOException;
+import titan.ccp.model.sensorregistry.ImmutableSensorRegistry;
+
+/**
+ * {@link StreamSerializer} for Hazelcast Jet to serialize and deserialize an
+ * {@link ImmutableSensorRegistry}.
+ */
+public class ImmutableSensorRegistryUc4Serializer
+    implements StreamSerializer<ImmutableSensorRegistry> {
+
+  private static final int TYPE_ID = 3;
+
+  @Override
+  public int getTypeId() {
+    return TYPE_ID;
+  }
+
+  @Override
+  public void write(final ObjectDataOutput out, final ImmutableSensorRegistry object)
+      throws IOException {
+    final String sensorRegistryJson = object.toJson();
+    out.writeString(sensorRegistryJson);
+  }
+
+  @Override
+  public ImmutableSensorRegistry read(final ObjectDataInput in) throws IOException {
+    final String sensorRegistryJson = in.readString();
+    return (ImmutableSensorRegistry) ImmutableSensorRegistry.fromJson(sensorRegistryJson);
+  }
+
+}
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/SensorGroupKey.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/SensorGroupKey.java
new file mode 100644
index 0000000000000000000000000000000000000000..24114cc90a709c99e74495714559c12324e07788
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/SensorGroupKey.java
@@ -0,0 +1,50 @@
+package rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics;
+
+import java.util.Objects;
+
+/**
+ * Structure (sensorId, group).
+ */
+public class SensorGroupKey {
+
+  private final String sensorId;
+  private final String group;
+
+  public SensorGroupKey(final String sensorId, final String group) {
+    this.sensorId = sensorId;
+    this.group = group;
+  }
+
+  public String getSensorId() {
+    return this.sensorId;
+  }
+
+  public String getGroup() {
+    return this.group;
+  }
+
+  @Override
+  public String toString() {
+    return "[SensorId: " + this.sensorId + "; Group: " + this.group + "]";
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(this.sensorId, this.group);
+  }
+
+  @Override
+  public boolean equals(final Object obj) {
+    if (obj == this) {
+      return true;
+    }
+    if (obj instanceof SensorGroupKey) {
+      final SensorGroupKey other = (SensorGroupKey) obj;
+      return Objects.equals(this.sensorId, other.sensorId)
+          && Objects.equals(this.group, other.group);
+    }
+    return false;
+  }
+
+
+}
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/SensorGroupKeySerializer.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/SensorGroupKeySerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..12a46b9d8f91ea145f614654a6ce9813b9014290
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/SensorGroupKeySerializer.java
@@ -0,0 +1,31 @@
+package rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics;
+
+import com.hazelcast.nio.ObjectDataInput;
+import com.hazelcast.nio.ObjectDataOutput;
+import com.hazelcast.nio.serialization.StreamSerializer;
+import java.io.IOException;
+
+/**
+ * Serializes and Deserializes a SensorGroupKey.
+ */
+public class SensorGroupKeySerializer implements StreamSerializer<SensorGroupKey> {
+
+  private static final int TYPE_ID = 2;
+
+  @Override
+  public int getTypeId() {
+    return TYPE_ID;
+  }
+
+  @Override
+  public void write(final ObjectDataOutput out, final SensorGroupKey key) throws IOException {
+    out.writeString(key.getSensorId());
+    out.writeString(key.getGroup());
+  }
+
+  @Override
+  public SensorGroupKey read(final ObjectDataInput in) throws IOException {
+    return new SensorGroupKey(in.readString(), in.readString());
+  }
+
+}
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ValueGroup.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ValueGroup.java
new file mode 100644
index 0000000000000000000000000000000000000000..893efcf74fe8a16202d795fca5cc43b63190dc50
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ValueGroup.java
@@ -0,0 +1,59 @@
+package rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics;
+
+import java.util.Objects;
+import java.util.Set;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * Structure: (valueInW, Set(Groups)).
+ */
+public class ValueGroup {
+
+  private final ActivePowerRecord record;
+  private final Set<String> groups;
+
+  public ValueGroup(final ActivePowerRecord record, final Set<String> groups) {
+    this.record = record;
+    this.groups = groups;
+  }
+
+  public ActivePowerRecord getRecord() {
+    return this.record;
+  }
+
+  public Double getValueInW() {
+    return this.record.getValueInW();
+  }
+
+  public Set<String> getGroups() {
+    return this.groups;
+  }
+
+  @Override
+  public String toString() {
+    String groupString = "[";
+    for (final String group : this.groups) {
+      groupString = groupString + group + "/";// NOPMD
+    }
+    return this.record.getValueInW() + ";" + groupString + "]";
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(this.record, this.groups);
+  }
+
+  @Override
+  public boolean equals(final Object obj) {
+    if (obj == this) {
+      return true;
+    }
+    if (obj instanceof ValueGroup) {
+      final ValueGroup other = (ValueGroup) obj;
+      return Objects.equals(this.record.getValueInW(), other.getValueInW())
+          && this.groups.containsAll(other.groups);
+    }
+    return false;
+  }
+
+}
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ValueGroupSerializer.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ValueGroupSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..e136d1da0cd8362fed4f76807e7f8725c2075b7f
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ValueGroupSerializer.java
@@ -0,0 +1,33 @@
+package rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics;
+
+import com.hazelcast.nio.ObjectDataInput;
+import com.hazelcast.nio.ObjectDataOutput;
+import com.hazelcast.nio.serialization.StreamSerializer;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+
+/** A pipeline serializer for the HourOfDayKey to allow for parallelization. */
+public class ValueGroupSerializer implements StreamSerializer<ValueGroup> {
+
+  private static final int TYPE_ID = 1;
+
+  @Override
+  public int getTypeId() {
+    return TYPE_ID;
+  }
+
+  @Override
+  public void write(final ObjectDataOutput out, final ValueGroup key) throws IOException {
+    out.writeObject(key);
+    out.writeString(String.join(",", key.getGroups()));
+  }
+
+  @Override
+  public ValueGroup read(final ObjectDataInput in) throws IOException {
+    return new ValueGroup(in.readObject(ValueGroup.class),
+        new HashSet<>(Arrays.asList(in.readString().split(","))));
+  }
+
+}
+
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/resources/META-INF/application.properties b/theodolite-benchmarks/uc4-hazelcastjet/src/main/resources/META-INF/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..e3371cc87e20e85e6e8c327955537e6e49dab86e
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/resources/META-INF/application.properties
@@ -0,0 +1,8 @@
+application.name=theodolite-uc1-application
+application.version=0.0.1
+
+kafka.bootstrap.servers=localhost:9092
+kafka.input.topic=input
+
+schema.registry.url=http://localhost:8081
+
diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4PipelineTest.java b/theodolite-benchmarks/uc4-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4PipelineTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b74c2874b92a51b138ffe8b44b1cf750dfce5880
--- /dev/null
+++ b/theodolite-benchmarks/uc4-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4PipelineTest.java
@@ -0,0 +1,226 @@
+package rocks.theodolite.benchmarks.uc4.hazelcastjet;
+
+import com.hazelcast.jet.Jet;
+import com.hazelcast.jet.JetInstance;
+import com.hazelcast.jet.config.JetConfig;
+import com.hazelcast.jet.config.JobConfig;
+import com.hazelcast.jet.core.JetTestSupport;
+import com.hazelcast.jet.pipeline.Pipeline;
+import com.hazelcast.jet.pipeline.Sinks;
+import com.hazelcast.jet.pipeline.StreamSource;
+import com.hazelcast.jet.pipeline.StreamStage;
+import com.hazelcast.jet.pipeline.test.AssertionCompletedException;
+import com.hazelcast.jet.pipeline.test.Assertions;
+import com.hazelcast.jet.pipeline.test.TestSources;
+import com.hazelcast.jet.test.SerialTest;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.concurrent.CompletionException;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.Uc4PipelineBuilder;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ImmutableSensorRegistryUc4Serializer;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.SensorGroupKey;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.SensorGroupKeySerializer;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ValueGroup;
+import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ValueGroupSerializer;
+import titan.ccp.configuration.events.Event;
+import titan.ccp.model.records.ActivePowerRecord;
+import titan.ccp.model.records.AggregatedActivePowerRecord;
+import titan.ccp.model.sensorregistry.ImmutableSensorRegistry;
+import titan.ccp.model.sensorregistry.MachineSensor;
+import titan.ccp.model.sensorregistry.MutableAggregatedSensor;
+import titan.ccp.model.sensorregistry.MutableSensorRegistry;
+
+@Category(SerialTest.class)
+public class Uc4PipelineTest extends JetTestSupport {
+
+  // TEst Machinery
+  JetInstance testInstance = null;
+  Pipeline testPipeline = null;
+  StreamStage<Entry<String, AggregatedActivePowerRecord>> uc4Topology = null;
+
+  @Before
+  public void buildUc4Pipeline() {
+
+    // Setup Configuration
+    final int testItemsPerSecond = 2;
+    final String testSensorName = "TEST-SENSOR";
+    final String testLevel1GroupName = "TEST-LEVEL1-GROUP";
+    final String testLevel2GroupName = "TEST-LEVEL2-GROUP";
+    final Double testValueInW = 10.0;
+    final int testWindowSize = 5000; // As window size is bugged, not necessary.
+
+    // Create mock jet instance with configuration
+    final String testClusterName = randomName();
+    final JetConfig testJetConfig = new JetConfig();
+    testJetConfig.getHazelcastConfig().setClusterName(testClusterName);
+    this.testInstance = this.createJetMember(testJetConfig);
+
+    // Create test source 1 : Input Values
+    final StreamSource<Entry<String, ActivePowerRecord>> testInputSource =
+        TestSources.itemStream(testItemsPerSecond, (timestamp, item) -> {
+          final ActivePowerRecord testRecord =
+              new ActivePowerRecord(testSensorName, timestamp, testValueInW);
+          final Entry<String, ActivePowerRecord> testEntry =
+              Map.entry(testSensorName, testRecord);
+          return testEntry;
+        });
+
+    // Create test source 2 : Mock aggregation Values
+    final StreamSource<Entry<String, AggregatedActivePowerRecord>> testAggregationSource =
+        TestSources.itemStream(testItemsPerSecond, (timestamp, item) -> {
+
+          AggregatedActivePowerRecord test =
+              new AggregatedActivePowerRecord(testSensorName,
+                  System.currentTimeMillis(),
+                  1L,
+                  testValueInW,
+                  testValueInW);
+
+          final ActivePowerRecord testAggValue =
+              new ActivePowerRecord(testSensorName,
+                  System.currentTimeMillis(),
+                  testValueInW);
+
+          final Entry<String, AggregatedActivePowerRecord> testEntry =
+              Map.entry(testLevel1GroupName, test);
+          return testEntry;
+        });
+
+
+    // Create test source 3 : Mock Config Values
+    final StreamSource<Entry<Event, String>> testConfigSource =
+        TestSources.itemStream(testItemsPerSecond, (timestamp, item) -> {
+          final Event theEvent = Event.SENSOR_REGISTRY_CHANGED;
+
+          // Topology:
+          // level2Group -> level1Group -> testSensor
+          
+          // Create Registry
+          final MutableSensorRegistry testRegistry = new MutableSensorRegistry(testLevel2GroupName);
+          // Add Sensors
+          final MutableAggregatedSensor topLevelSensor = testRegistry.getTopLevelSensor();
+          final MutableAggregatedSensor level1GroupSensor =
+              topLevelSensor.addChildAggregatedSensor(testLevel1GroupName);
+          final MachineSensor inputSensor = level1GroupSensor.addChildMachineSensor(testSensorName);
+
+          final String stringRegistry = testRegistry.toJson();
+          final Entry<Event, String> testEntry =
+              Map.entry(theEvent, stringRegistry);
+          return testEntry;
+        });
+
+    // Create pipeline to test
+    final Uc4PipelineBuilder pipelineBuilder = new Uc4PipelineBuilder();
+    this.testPipeline = Pipeline.create();
+    this.uc4Topology = pipelineBuilder.extendUc4Topology(testPipeline,
+        testInputSource, testAggregationSource, testConfigSource, testWindowSize);
+
+    this.uc4Topology.writeTo(Sinks.logger());
+  }
+
+  /**
+   * Tests if no items reach the end before the first window ends.
+   */
+  @Test
+  public void testOutput() {
+
+//    System.out.println("DEBUG DEBUG DEBUG || ENTERED TEST 1");
+    
+    // Assertion Configuration
+    final int timeout = 20;
+    final String testSensorName = "TEST-SENSOR";
+    final String testLevel1GroupName = "TEST-LEVEL1-GROUP";
+    final String testLevel2GroupName = "TEST-LEVEL2-GROUP";
+    final double testValueInW = 10.0;
+
+
+    // Assertion
+    this.uc4Topology.apply(Assertions.assertCollectedEventually(timeout, 
+        collection -> {
+          System.out.println("DEBUG || ENTERED ASSERTION COLLECTED EVENTUALLY");
+
+          boolean allOkay = false;
+
+          boolean testLevel1contained = false;
+          boolean testLevel2contained = false;
+          boolean averageEqTest = true;
+          boolean avOk = true;
+
+
+          if (collection != null) {
+            System.out.println("Collection size: " + collection.size());
+
+
+            for (final Entry<String, AggregatedActivePowerRecord> entry : collection) {
+              System.out.println("DEBUG || " + entry.toString());
+
+              final String key = entry.getKey();
+              final AggregatedActivePowerRecord agg = entry.getValue();
+
+
+              if (Objects.equals(key, testLevel1GroupName)) {
+                testLevel1contained = true;
+              }
+
+              if(Objects.equals(key, testLevel2GroupName)){
+                testLevel2contained = true;
+              }
+
+              if (testValueInW != agg.getAverageInW()){
+                averageEqTest = false;
+              }
+
+              final double average = agg.getSumInW() / agg.getCount();
+              if (average != agg.getAverageInW()) {
+                avOk = false;
+              }
+
+            }
+            allOkay = testLevel1contained && testLevel2contained && averageEqTest && avOk;
+          }
+
+          System.out.println("testLevel1contained: " + testLevel1contained);
+          System.out.println("testLevel2contained: " + testLevel2contained);
+          System.out.println("averageEqTest: " + averageEqTest);
+          System.out.println("avOk: " + avOk);
+
+          Assert.assertTrue("Assertion did not complete!", allOkay);
+          
+        }));
+
+    try{
+
+      final JobConfig jobConfig = new JobConfig()
+          .registerSerializer(ValueGroup.class, ValueGroupSerializer.class)
+          .registerSerializer(SensorGroupKey.class, SensorGroupKeySerializer.class)
+          .registerSerializer(ImmutableSensorRegistry.class,
+              ImmutableSensorRegistryUc4Serializer.class);
+      this.testInstance.newJob(this.testPipeline, jobConfig).join();
+
+    } catch (final CompletionException e) {
+      final String errorMsg = e.getCause().getMessage();
+      Assert.assertTrue(
+          "Job was expected to complete with AssertionCompletedException, but completed with: "
+              + e.getCause(),
+          errorMsg.contains(AssertionCompletedException.class.getName()));
+    } catch (Exception e){
+      System.out.println("ERRORORORO TEST BROKEN !!!!");
+      System.out.println(e);
+    }
+  }
+
+
+  @After
+  public void after() {
+    System.out.println("Shutting down");
+    // Shuts down all running Jet Instances
+    Jet.shutdownAll();
+  }
+
+}
diff --git a/theodolite-benchmarks/uc4-kstreams/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc4-kstreams/.settings/org.eclipse.jdt.ui.prefs
index fa98ca63d77bdee891150bd6713f70197a75cefc..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc4-kstreams/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc4-kstreams/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,25 +12,72 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
 cleanup.remove_redundant_semicolons=true
@@ -37,6 +85,7 @@ cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,27 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -79,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -114,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc4-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc4-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/uc4-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/uc4-kstreams/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/uc4-kstreams/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc4-kstreams/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/uc4-kstreams/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/uc4-kstreams/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc4-kstreams/build.gradle b/theodolite-benchmarks/uc4-kstreams/build.gradle
index 83212a499ae344ea44beb3c2b98aec147dda8488..52d201783364d72d2fda9aeeb39f9e2dba708ce7 100644
--- a/theodolite-benchmarks/uc4-kstreams/build.gradle
+++ b/theodolite-benchmarks/uc4-kstreams/build.gradle
@@ -2,4 +2,4 @@ plugins {
   id 'theodolite.kstreams'
 }
 
-mainClassName = "theodolite.uc4.application.AggregationService"
+mainClassName = "rocks.theodolite.benchmarks.uc4.kstreams.AggregationService"
diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/application/AggregationService.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/AggregationService.java
similarity index 92%
rename from theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/application/AggregationService.java
rename to theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/AggregationService.java
index 5c9d0910e7fbc60e58b13fc838f7ef2407de2aa3..341c37bc086dabb3a93dcd3b0f221dd91007b8b3 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/application/AggregationService.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/AggregationService.java
@@ -1,11 +1,10 @@
-package theodolite.uc4.application;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import java.time.Duration;
 import java.util.concurrent.CompletableFuture;
 import org.apache.commons.configuration2.Configuration;
 import org.apache.kafka.streams.KafkaStreams;
-import theodolite.commons.kafkastreams.ConfigurationKeys;
-import theodolite.uc4.streamprocessing.Uc4KafkaStreamsBuilder;
+import rocks.theodolite.benchmarks.commons.kstreams.ConfigurationKeys;
 import titan.ccp.common.configuration.ServiceConfigurations;
 
 /**
diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/ChildParentsTransformer.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ChildParentsTransformer.java
similarity index 98%
rename from theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/ChildParentsTransformer.java
rename to theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ChildParentsTransformer.java
index db28c86bce79caa4345a3a2bc7914c3e2bbd1a32..bdc8fc7d4267fbdb427d8dc217ef296c0553da1b 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/ChildParentsTransformer.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ChildParentsTransformer.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import java.util.Map;
 import java.util.Optional;
diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/ChildParentsTransformerSupplier.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ChildParentsTransformerSupplier.java
similarity index 96%
rename from theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/ChildParentsTransformerSupplier.java
rename to theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ChildParentsTransformerSupplier.java
index d17757d6800890eaf5260af9c25914344ca4a625..538643f0cdb119988e446f3eae793e2efcccadd6 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/ChildParentsTransformerSupplier.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ChildParentsTransformerSupplier.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import java.util.Map;
 import java.util.Optional;
diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/JointFlatTransformer.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointFlatTransformer.java
similarity index 98%
rename from theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/JointFlatTransformer.java
rename to theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointFlatTransformer.java
index d3500adff664cba8f3f92707a0adba34534404b7..38cbca81d664ca72494525263d8a7ab3a7523bfc 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/JointFlatTransformer.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointFlatTransformer.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import com.google.common.base.MoreObjects;
 import java.util.ArrayList;
diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/JointFlatTransformerSupplier.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointFlatTransformerSupplier.java
similarity index 96%
rename from theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/JointFlatTransformerSupplier.java
rename to theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointFlatTransformerSupplier.java
index 51c7ce1f6cb144c88356ef1b32bdfce400e1ffb4..2e635ec368bca87bdb882580b51f763abba8f32a 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/JointFlatTransformerSupplier.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointFlatTransformerSupplier.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import java.util.Map;
 import java.util.Set;
diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/JointRecordParents.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointRecordParents.java
similarity index 96%
rename from theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/JointRecordParents.java
rename to theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointRecordParents.java
index e9a5a824e43dfbab83151da5c2a8f18f9105f494..5892c6d3ac84c6d1ff56cfb440186e07fd9d9eb0 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/JointRecordParents.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointRecordParents.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import java.util.Objects;
 import java.util.Set;
diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/OptionalParentsSerde.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/OptionalParentsSerde.java
similarity index 96%
rename from theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/OptionalParentsSerde.java
rename to theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/OptionalParentsSerde.java
index a1e9767da047951e04d4c3914c2d1b36bd18626b..3738fadd52b22abb8e13f20ae6066017112f0455 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/OptionalParentsSerde.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/OptionalParentsSerde.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import java.util.HashSet;
 import java.util.Optional;
diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/ParentsSerde.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ParentsSerde.java
similarity index 95%
rename from theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/ParentsSerde.java
rename to theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ParentsSerde.java
index df6f848b5dfde10a96aceaf4d4a293364d52b982..dac58c84bc1914b4e54fe5eb6da0930204e34eb5 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/ParentsSerde.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ParentsSerde.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import java.util.HashSet;
 import java.util.Set;
diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/RecordAggregator.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/RecordAggregator.java
similarity index 96%
rename from theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/RecordAggregator.java
rename to theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/RecordAggregator.java
index 34ef3762d6a3219958329762ce6e39844684068a..d107dedbfdb58489a6f00e2baf248f15bb823db9 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/RecordAggregator.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/RecordAggregator.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import org.apache.kafka.streams.kstream.Windowed;
 import titan.ccp.model.records.ActivePowerRecord;
diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/SensorParentKey.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/SensorParentKey.java
similarity index 95%
rename from theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/SensorParentKey.java
rename to theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/SensorParentKey.java
index 667cc6d5ee83a41f7c04fc8074a18ef1a9422b0e..8c700f8075a67d7e8ffb40e4b3c92f23109e1cc1 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/SensorParentKey.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/SensorParentKey.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import java.util.Objects;
 
diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/SensorParentKeySerde.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/SensorParentKeySerde.java
similarity index 95%
rename from theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/SensorParentKeySerde.java
rename to theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/SensorParentKeySerde.java
index 63b9e44b5a7bde8f47fe7620b286aefa7fc60841..80fd16f64c6f08e32a89bb3558b61d3f560be890 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/SensorParentKeySerde.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/SensorParentKeySerde.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import org.apache.kafka.common.serialization.Serde;
 import titan.ccp.common.kafka.simpleserdes.BufferSerde;
diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/TopologyBuilder.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/TopologyBuilder.java
similarity index 98%
rename from theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/TopologyBuilder.java
rename to theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/TopologyBuilder.java
index 623870313cd341d0594fee38d2fd0ae297abbeae..fbd3ed109965b103e4f1cdeb4324581bc6c82e8b 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/TopologyBuilder.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/TopologyBuilder.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import java.time.Duration;
 import java.util.Properties;
@@ -146,7 +146,7 @@ public class TopologyBuilder {
         .groupByKey(Grouped.with(
             SensorParentKeySerde.serde(),
             this.srAvroSerdeFactory.forValues()))
-        .windowedBy(TimeWindows.of(this.emitPeriod).grace(this.gracePeriod))
+        .windowedBy(TimeWindows.ofSizeAndGrace(this.emitPeriod, this.gracePeriod))
         .reduce(
             // TODO Configurable window aggregation function
             (oldVal, newVal) -> newVal.getTimestamp() >= oldVal.getTimestamp() ? newVal : oldVal,
diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/Uc4KafkaStreamsBuilder.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/Uc4KafkaStreamsBuilder.java
similarity index 95%
rename from theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/Uc4KafkaStreamsBuilder.java
rename to theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/Uc4KafkaStreamsBuilder.java
index 9f1af3ba066bcdfef7f8e9073947d570a1327515..4d2b96ccb751dbb804eab0806303312a88702dc0 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/main/java/theodolite/uc4/streamprocessing/Uc4KafkaStreamsBuilder.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/Uc4KafkaStreamsBuilder.java
@@ -1,11 +1,11 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import java.time.Duration;
 import java.util.Objects;
 import java.util.Properties;
 import org.apache.commons.configuration2.Configuration;
 import org.apache.kafka.streams.Topology;
-import theodolite.commons.kafkastreams.KafkaStreamsBuilder;
+import rocks.theodolite.benchmarks.commons.kstreams.KafkaStreamsBuilder;
 import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory;
 
 /**
diff --git a/theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/OptionalParentsSerdeTest.java b/theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/OptionalParentsSerdeTest.java
similarity index 94%
rename from theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/OptionalParentsSerdeTest.java
rename to theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/OptionalParentsSerdeTest.java
index 600fc0b15ccc3ac3d902565fba1d073e37d98d0f..65ab88e7167f34ff94d7e011ae2ee9707a5ddad4 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/OptionalParentsSerdeTest.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/OptionalParentsSerdeTest.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import java.util.Optional;
 import java.util.Set;
diff --git a/theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/ParentsSerdeTest.java b/theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/ParentsSerdeTest.java
similarity index 89%
rename from theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/ParentsSerdeTest.java
rename to theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/ParentsSerdeTest.java
index 994593e27914af2ad56693e4b08b8143b27000b7..65e9bd7c32e6b9bb6cfb6bd54fb29ab32cfb7f3a 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/ParentsSerdeTest.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/ParentsSerdeTest.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import java.util.Set;
 import org.junit.Test;
diff --git a/theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/SensorParentKeySerdeTest.java b/theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/SensorParentKeySerdeTest.java
similarity index 90%
rename from theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/SensorParentKeySerdeTest.java
rename to theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/SensorParentKeySerdeTest.java
index 34f87fa98ca7de7d6ca24a49a73729e5ecc2e74b..b71a0188020b74c5a21b4d70a762a818d2c8f23b 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/SensorParentKeySerdeTest.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/SensorParentKeySerdeTest.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import org.junit.Test;
 
diff --git a/theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/SerdeTester.java b/theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/SerdeTester.java
similarity index 92%
rename from theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/SerdeTester.java
rename to theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/SerdeTester.java
index b5d5f942dac068379fe90a7462545adb7a11e7df..bf893c04f447ea70f62ed5fc15e1fc19a4be22a3 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/SerdeTester.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/SerdeTester.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import static org.junit.Assert.assertEquals;
 import java.util.function.Function;
diff --git a/theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/SerdeTesterFactory.java b/theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/SerdeTesterFactory.java
similarity index 92%
rename from theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/SerdeTesterFactory.java
rename to theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/SerdeTesterFactory.java
index e8083ed778c450ef6717ca7b9c73daa3d96a7af3..ade3763fc55dd409a4e321570418f5629fb52959 100644
--- a/theodolite-benchmarks/uc4-kstreams/src/test/java/theodolite/uc4/streamprocessing/SerdeTesterFactory.java
+++ b/theodolite-benchmarks/uc4-kstreams/src/test/java/rocks/theodolite/benchmarks/uc4/kstreams/SerdeTesterFactory.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.streamprocessing;
+package rocks.theodolite.benchmarks.uc4.kstreams;
 
 import org.apache.kafka.common.serialization.Serde;
 
diff --git a/theodolite-benchmarks/uc4-load-generator/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/uc4-load-generator/.settings/org.eclipse.jdt.ui.prefs
index 4d01df75552c562406705858b6368ecf59d6e82f..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d 100644
--- a/theodolite-benchmarks/uc4-load-generator/.settings/org.eclipse.jdt.ui.prefs
+++ b/theodolite-benchmarks/uc4-load-generator/.settings/org.eclipse.jdt.ui.prefs
@@ -1,3 +1,4 @@
+cleanup.add_all=false
 cleanup.add_default_serial_version_id=true
 cleanup.add_generated_serial_version_id=false
 cleanup.add_missing_annotations=true
@@ -11,25 +12,72 @@ cleanup.always_use_blocks=true
 cleanup.always_use_parentheses_in_expressions=false
 cleanup.always_use_this_for_non_static_field_access=true
 cleanup.always_use_this_for_non_static_method_access=true
+cleanup.array_with_curly=false
+cleanup.arrays_fill=false
+cleanup.bitwise_conditional_expression=false
+cleanup.boolean_literal=false
+cleanup.boolean_value_rather_than_comparison=true
+cleanup.break_loop=false
+cleanup.collection_cloning=false
+cleanup.comparing_on_criteria=false
+cleanup.comparison_statement=false
+cleanup.controlflow_merge=false
 cleanup.convert_functional_interfaces=false
 cleanup.convert_to_enhanced_for_loop=true
+cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true
+cleanup.convert_to_switch_expressions=false
 cleanup.correct_indentation=true
+cleanup.do_while_rather_than_while=true
+cleanup.double_negation=false
+cleanup.else_if=false
+cleanup.embedded_if=false
+cleanup.evaluate_nullable=false
+cleanup.extract_increment=false
 cleanup.format_source_code=true
 cleanup.format_source_code_changes_only=false
+cleanup.hash=false
+cleanup.if_condition=false
 cleanup.insert_inferred_type_arguments=false
+cleanup.instanceof=false
+cleanup.instanceof_keyword=false
+cleanup.invert_equals=false
+cleanup.join=false
+cleanup.lazy_logical_operator=false
 cleanup.make_local_variable_final=true
 cleanup.make_parameters_final=true
 cleanup.make_private_fields_final=true
 cleanup.make_type_abstract_if_missing_method=false
 cleanup.make_variable_declarations_final=true
+cleanup.map_cloning=false
+cleanup.merge_conditional_blocks=false
+cleanup.multi_catch=false
 cleanup.never_use_blocks=false
 cleanup.never_use_parentheses_in_expressions=true
+cleanup.no_string_creation=false
+cleanup.no_super=false
+cleanup.number_suffix=false
+cleanup.objects_equals=false
+cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true
+cleanup.operand_factorization=false
 cleanup.organize_imports=true
+cleanup.overridden_assignment=false
+cleanup.plain_replacement=false
+cleanup.precompile_regex=false
+cleanup.primitive_comparison=false
+cleanup.primitive_parsing=false
+cleanup.primitive_rather_than_wrapper=true
+cleanup.primitive_serialization=false
+cleanup.pull_out_if_from_if_else=false
+cleanup.pull_up_assignment=false
+cleanup.push_down_negation=false
 cleanup.qualify_static_field_accesses_with_declaring_class=false
 cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 cleanup.qualify_static_member_accesses_with_declaring_class=true
 cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.reduce_indentation=false
+cleanup.redundant_comparator=false
+cleanup.redundant_falling_through_block_end=false
 cleanup.remove_private_constructors=true
 cleanup.remove_redundant_modifiers=false
 cleanup.remove_redundant_semicolons=true
@@ -37,6 +85,7 @@ cleanup.remove_redundant_type_arguments=true
 cleanup.remove_trailing_whitespaces=true
 cleanup.remove_trailing_whitespaces_all=true
 cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_array_creation=false
 cleanup.remove_unnecessary_casts=true
 cleanup.remove_unnecessary_nls_tags=true
 cleanup.remove_unused_imports=true
@@ -45,28 +94,59 @@ cleanup.remove_unused_private_fields=true
 cleanup.remove_unused_private_members=false
 cleanup.remove_unused_private_methods=true
 cleanup.remove_unused_private_types=true
+cleanup.return_expression=false
+cleanup.simplify_lambda_expression_and_method_ref=false
+cleanup.single_used_field=false
 cleanup.sort_members=false
 cleanup.sort_members_all=false
+cleanup.standard_comparison=false
+cleanup.static_inner_class=false
+cleanup.strictly_equal_or_different=false
+cleanup.stringbuffer_to_stringbuilder=false
+cleanup.stringbuilder=false
+cleanup.stringbuilder_for_local_vars=true
+cleanup.stringconcat_to_textblock=false
+cleanup.substring=false
+cleanup.switch=false
+cleanup.system_property=false
+cleanup.system_property_boolean=false
+cleanup.system_property_file_encoding=false
+cleanup.system_property_file_separator=false
+cleanup.system_property_line_separator=false
+cleanup.system_property_path_separator=false
+cleanup.ternary_operator=false
+cleanup.try_with_resource=false
+cleanup.unlooped_while=false
+cleanup.unreachable_block=false
 cleanup.use_anonymous_class_creation=false
+cleanup.use_autoboxing=false
 cleanup.use_blocks=true
 cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_directly_map_method=false
 cleanup.use_lambda=true
 cleanup.use_parentheses_in_expressions=true
+cleanup.use_string_is_blank=false
 cleanup.use_this_for_non_static_field_access=true
 cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 cleanup.use_this_for_non_static_method_access=true
 cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup.use_unboxing=false
+cleanup.use_var=false
+cleanup.useless_continue=false
+cleanup.useless_return=false
+cleanup.valueof_rather_than_instantiation=false
 cleanup_profile=_CAU-SE-Style
 cleanup_settings_version=2
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 formatter_profile=_CAU-SE-Style
-formatter_settings_version=15
+formatter_settings_version=21
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.importorder=
 org.eclipse.jdt.ui.ondemandthreshold=99
 org.eclipse.jdt.ui.staticondemandthreshold=99
 org.eclipse.jdt.ui.text.custom_code_templates=
+sp_cleanup.add_all=false
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_generated_serial_version_id=false
 sp_cleanup.add_missing_annotations=true
@@ -80,33 +160,81 @@ sp_cleanup.always_use_blocks=true
 sp_cleanup.always_use_parentheses_in_expressions=false
 sp_cleanup.always_use_this_for_non_static_field_access=true
 sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.array_with_curly=false
+sp_cleanup.arrays_fill=false
+sp_cleanup.bitwise_conditional_expression=false
+sp_cleanup.boolean_literal=false
+sp_cleanup.boolean_value_rather_than_comparison=false
+sp_cleanup.break_loop=false
+sp_cleanup.collection_cloning=false
+sp_cleanup.comparing_on_criteria=true
+sp_cleanup.comparison_statement=false
+sp_cleanup.controlflow_merge=false
 sp_cleanup.convert_functional_interfaces=false
 sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false
+sp_cleanup.convert_to_switch_expressions=false
 sp_cleanup.correct_indentation=true
+sp_cleanup.do_while_rather_than_while=false
+sp_cleanup.double_negation=false
+sp_cleanup.else_if=false
+sp_cleanup.embedded_if=false
+sp_cleanup.evaluate_nullable=false
+sp_cleanup.extract_increment=false
 sp_cleanup.format_source_code=true
 sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.hash=false
+sp_cleanup.if_condition=false
 sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.instanceof=false
+sp_cleanup.instanceof_keyword=false
+sp_cleanup.invert_equals=false
+sp_cleanup.join=false
+sp_cleanup.lazy_logical_operator=false
 sp_cleanup.make_local_variable_final=true
 sp_cleanup.make_parameters_final=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_type_abstract_if_missing_method=false
 sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.map_cloning=false
+sp_cleanup.merge_conditional_blocks=false
+sp_cleanup.multi_catch=false
 sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.no_string_creation=false
+sp_cleanup.no_super=false
+sp_cleanup.number_suffix=false
+sp_cleanup.objects_equals=false
 sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false
+sp_cleanup.operand_factorization=false
 sp_cleanup.organize_imports=true
+sp_cleanup.overridden_assignment=false
+sp_cleanup.plain_replacement=false
+sp_cleanup.precompile_regex=false
+sp_cleanup.primitive_comparison=false
+sp_cleanup.primitive_parsing=false
+sp_cleanup.primitive_rather_than_wrapper=false
+sp_cleanup.primitive_serialization=false
+sp_cleanup.pull_out_if_from_if_else=false
+sp_cleanup.pull_up_assignment=false
+sp_cleanup.push_down_negation=false
 sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
 sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.reduce_indentation=false
+sp_cleanup.redundant_comparator=false
+sp_cleanup.redundant_falling_through_block_end=false
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_redundant_modifiers=false
-sp_cleanup.remove_redundant_semicolons=true
-sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_redundant_semicolons=false
+sp_cleanup.remove_redundant_type_arguments=false
 sp_cleanup.remove_trailing_whitespaces=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_array_creation=false
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unnecessary_nls_tags=true
 sp_cleanup.remove_unused_imports=true
@@ -115,14 +243,44 @@ sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_members=false
 sp_cleanup.remove_unused_private_methods=true
 sp_cleanup.remove_unused_private_types=true
+sp_cleanup.return_expression=false
+sp_cleanup.simplify_lambda_expression_and_method_ref=false
+sp_cleanup.single_used_field=false
 sp_cleanup.sort_members=false
 sp_cleanup.sort_members_all=false
+sp_cleanup.standard_comparison=false
+sp_cleanup.static_inner_class=false
+sp_cleanup.strictly_equal_or_different=false
+sp_cleanup.stringbuffer_to_stringbuilder=false
+sp_cleanup.stringbuilder=false
+sp_cleanup.stringbuilder_for_local_vars=false
+sp_cleanup.stringconcat_to_textblock=false
+sp_cleanup.substring=false
+sp_cleanup.switch=false
+sp_cleanup.system_property=false
+sp_cleanup.system_property_boolean=false
+sp_cleanup.system_property_file_encoding=false
+sp_cleanup.system_property_file_separator=false
+sp_cleanup.system_property_line_separator=false
+sp_cleanup.system_property_path_separator=false
+sp_cleanup.ternary_operator=false
+sp_cleanup.try_with_resource=false
+sp_cleanup.unlooped_while=false
+sp_cleanup.unreachable_block=false
 sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_autoboxing=false
 sp_cleanup.use_blocks=true
 sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_directly_map_method=false
 sp_cleanup.use_lambda=true
 sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_string_is_blank=false
 sp_cleanup.use_this_for_non_static_field_access=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
 sp_cleanup.use_this_for_non_static_method_access=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+sp_cleanup.use_unboxing=false
+sp_cleanup.use_var=false
+sp_cleanup.useless_continue=true
+sp_cleanup.useless_return=true
+sp_cleanup.valueof_rather_than_instantiation=false
diff --git a/theodolite-benchmarks/uc4-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/uc4-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs
index 87860c815222845c1d264d7d0ce498d3397f8280..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 100644
--- a/theodolite-benchmarks/uc4-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs
+++ b/theodolite-benchmarks/uc4-load-generator/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -1,4 +1,4 @@
 configFilePath=../config/checkstyle.xml
 customModulesJarPaths=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
diff --git a/theodolite-benchmarks/uc4-load-generator/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/uc4-load-generator/.settings/qa.eclipse.plugin.pmd.prefs
index efbcb8c9e5d449194a48ca1ea42b7d807b573db9..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a 100644
--- a/theodolite-benchmarks/uc4-load-generator/.settings/qa.eclipse.plugin.pmd.prefs
+++ b/theodolite-benchmarks/uc4-load-generator/.settings/qa.eclipse.plugin.pmd.prefs
@@ -1,4 +1,4 @@
 customRulesJars=
 eclipse.preferences.version=1
-enabled=true
+enabled=false
 ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/uc4-load-generator/build.gradle b/theodolite-benchmarks/uc4-load-generator/build.gradle
index 9785718056fa1a14d687a75237cd23b941ce7365..60d1c3bafd12580d6948d5a378be37a940332b72 100644
--- a/theodolite-benchmarks/uc4-load-generator/build.gradle
+++ b/theodolite-benchmarks/uc4-load-generator/build.gradle
@@ -2,4 +2,4 @@ plugins {
   id 'theodolite.load-generator'
 }
 
-mainClassName = "theodolite.uc4.workloadgenerator.LoadGenerator"
+mainClassName = "rocks.theodolite.benchmarks.uc4.loadgenerator.LoadGenerator"
diff --git a/theodolite-benchmarks/uc4-load-generator/src/main/java/theodolite/uc4/workloadgenerator/ConfigPublisher.java b/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/ConfigPublisher.java
similarity index 97%
rename from theodolite-benchmarks/uc4-load-generator/src/main/java/theodolite/uc4/workloadgenerator/ConfigPublisher.java
rename to theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/ConfigPublisher.java
index ad0ee7082da9116f9ccb66a79d48b36bfb30da2e..98f470b0df1873766c3bf56fb7e6a8eae0019ce4 100644
--- a/theodolite-benchmarks/uc4-load-generator/src/main/java/theodolite/uc4/workloadgenerator/ConfigPublisher.java
+++ b/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/ConfigPublisher.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.workloadgenerator;
+package rocks.theodolite.benchmarks.uc4.loadgenerator;
 
 import java.util.Properties;
 import java.util.concurrent.ExecutionException;
diff --git a/theodolite-benchmarks/uc4-load-generator/src/main/java/theodolite/uc4/workloadgenerator/LoadGenerator.java b/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/LoadGenerator.java
similarity index 91%
rename from theodolite-benchmarks/uc4-load-generator/src/main/java/theodolite/uc4/workloadgenerator/LoadGenerator.java
rename to theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/LoadGenerator.java
index 8320d16b98fa1d253064d08397d5df1bb8e17b79..2077de2d9918d46a7a3e671ae9820a7c7abadbfc 100644
--- a/theodolite-benchmarks/uc4-load-generator/src/main/java/theodolite/uc4/workloadgenerator/LoadGenerator.java
+++ b/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/LoadGenerator.java
@@ -1,9 +1,9 @@
-package theodolite.uc4.workloadgenerator;
+package rocks.theodolite.benchmarks.uc4.loadgenerator;
 
 import java.util.Objects;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import theodolite.commons.workloadgeneration.KeySpace;
+import rocks.theodolite.benchmarks.loadgenerator.KeySpace;
 import titan.ccp.configuration.events.Event;
 import titan.ccp.model.sensorregistry.SensorRegistry;
 
@@ -40,7 +40,7 @@ public final class LoadGenerator {
         new SensorRegistryBuilder(numNestedGroups, numSensors).build();
 
     LOGGER.info("Start workload generator for use case UC4");
-    theodolite.commons.workloadgeneration.LoadGenerator.fromEnvironment()
+    rocks.theodolite.benchmarks.loadgenerator.LoadGenerator.fromEnvironment()
         .withKeySpace(new KeySpace("s_", sensorRegistry.getMachineSensors().size()))
         .withBeforeAction(() -> {
           if (sendRegistry) {
diff --git a/theodolite-benchmarks/uc4-load-generator/src/main/java/theodolite/uc4/workloadgenerator/SensorRegistryBuilder.java b/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/SensorRegistryBuilder.java
similarity index 96%
rename from theodolite-benchmarks/uc4-load-generator/src/main/java/theodolite/uc4/workloadgenerator/SensorRegistryBuilder.java
rename to theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/SensorRegistryBuilder.java
index 60303056a01466b908b73e51377427f5d8347441..c69dffb6093f914111b8c74bc25f3ca3a0a34ae6 100644
--- a/theodolite-benchmarks/uc4-load-generator/src/main/java/theodolite/uc4/workloadgenerator/SensorRegistryBuilder.java
+++ b/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/SensorRegistryBuilder.java
@@ -1,4 +1,4 @@
-package theodolite.uc4.workloadgenerator;
+package rocks.theodolite.benchmarks.uc4.loadgenerator;
 
 import titan.ccp.model.sensorregistry.MutableAggregatedSensor;
 import titan.ccp.model.sensorregistry.MutableSensorRegistry;
diff --git a/theodolite-benchmarks/uc4-load-generator/src/test/java/theodolite/uc4/workloadgenerator/SensorRegistryBuilderTest.java b/theodolite-benchmarks/uc4-load-generator/src/test/java/rocks/theodolite/benchmarks/uc4/loadgenerator/SensorRegistryBuilderTest.java
similarity index 96%
rename from theodolite-benchmarks/uc4-load-generator/src/test/java/theodolite/uc4/workloadgenerator/SensorRegistryBuilderTest.java
rename to theodolite-benchmarks/uc4-load-generator/src/test/java/rocks/theodolite/benchmarks/uc4/loadgenerator/SensorRegistryBuilderTest.java
index 424c84ec96cdd90077fb7934686cd021b040e732..a169eddb10ac34b91b814a657bf327a79ae00ac4 100644
--- a/theodolite-benchmarks/uc4-load-generator/src/test/java/theodolite/uc4/workloadgenerator/SensorRegistryBuilderTest.java
+++ b/theodolite-benchmarks/uc4-load-generator/src/test/java/rocks/theodolite/benchmarks/uc4/loadgenerator/SensorRegistryBuilderTest.java
@@ -1,5 +1,4 @@
-package theodolite.uc4.workloadgenerator;
-
+package rocks.theodolite.benchmarks.uc4.loadgenerator;
 
 import java.util.Collection;
 import java.util.Set;
diff --git a/theodolite/README.md b/theodolite/README.md
index f662329f7eda3a39632581b7125a2f2f2feced8a..49019813c43e0b19e32e35703ca294b2b5c54cb0 100644
--- a/theodolite/README.md
+++ b/theodolite/README.md
@@ -51,7 +51,7 @@ Or, if you don't have GraalVM installed, you can run the native executable build
 ```
 
 You can then execute your native executable with:
-```./build/theodolite-0.7.0-SNAPSHOT-runner```
+```./build/theodolite-0.8.0-SNAPSHOT-runner```
 
 If you want to learn more about building native executables, please consult https://quarkus.io/guides/gradle-tooling.
 
diff --git a/theodolite/build.gradle b/theodolite/build.gradle
index a066e94f09b71720f9392947640b077b153ccb9c..7e10245b8605ba926ac171e260bc145378a0d8d8 100644
--- a/theodolite/build.gradle
+++ b/theodolite/build.gradle
@@ -37,7 +37,7 @@ dependencies {
 }
 
 group 'theodolite'
-version '0.7.0-SNAPSHOT'
+version '0.8.0-SNAPSHOT'
 
 java {
     sourceCompatibility = JavaVersion.VERSION_11
@@ -59,6 +59,12 @@ compileTestKotlin {
     kotlinOptions.jvmTarget = JavaVersion.VERSION_11
 }
 
+test {
+    // Required because of https://github.com/quarkusio/quarkus/issues/18973
+    minHeapSize = "256m"
+    maxHeapSize = "1024m"
+}
+
 detekt {
     failFast = true // fail build on any finding
     buildUponDefaultConfig = true
diff --git a/theodolite/crd/crd-benchmark.yaml b/theodolite/crd/crd-benchmark.yaml
index c901e61360c05b2f1cf2b1767a20f624eb262231..d73ec0105c7f97d0e425307fc4f21fd84d1e9b46 100644
--- a/theodolite/crd/crd-benchmark.yaml
+++ b/theodolite/crd/crd-benchmark.yaml
@@ -20,12 +20,16 @@ spec:
         properties:
           spec:
             type: object
-            required: ["sut", "loadGenerator", "resourceTypes", "loadTypes"]
+            required: ["sut", "loadGenerator", "resourceTypes", "loadTypes", "slos"]
             properties:
               name:
                 description: This field exists only for technical reasons and should not be set by the user. The value of the field will be overwritten.
                 type: string
                 default: ""
+              waitForResourcesEnabled:
+                description: If true, Theodolite waits to create the resource for the SUT until the infrastructure resources are ready, and analogously, Theodolite waits to create the load-gen resource until the resources of the SUT are ready.
+                type: boolean
+                default: false
               infrastructure:
                 description: (Optional) A list of file names that reference Kubernetes resources that are deployed on the cluster to create the required infrastructure.
                 type: object
@@ -425,6 +429,31 @@ spec:
                             additionalProperties: true
                             x-kubernetes-map-type: "granular"
                             default: {}
+              slos: # def of service level objectives
+                description: List of resource values for the specified resource type.
+                type: array
+                items:
+                  type: object
+                  required: ["name", "sloType", "prometheusUrl", "offset"]
+                  properties:
+                    name:
+                      description: The name of the SLO.
+                      type: string
+                    sloType:
+                      description: The type of the SLO. It must match 'lag trend'.
+                      type: string
+                    prometheusUrl:
+                      description: Connection string for Promehteus.
+                      type: string
+                    offset:
+                      description: Hours by which the start and end timestamp will be shifted (for different timezones).
+                      type: integer
+                    properties:
+                      description: (Optional) SLO specific additional arguments.
+                      type: object
+                      additionalProperties: true
+                      x-kubernetes-map-type: "granular"
+                      default: { }
               kafkaConfig:
                 description: Contains the Kafka configuration.
                 type: object
diff --git a/theodolite/crd/crd-execution.yaml b/theodolite/crd/crd-execution.yaml
index 92a8ca18d87009143620097caf2abfe8da202c82..0db251864bac3e6f2541534eec8895297b21cf39 100644
--- a/theodolite/crd/crd-execution.yaml
+++ b/theodolite/crd/crd-execution.yaml
@@ -20,7 +20,7 @@ spec:
         properties:
           spec:
             type: object
-            required: ["benchmark", "load", "resources", "slos", "execution", "configOverrides"]
+            required: ["benchmark", "loads", "resources", "execution", "configOverrides"]
             properties:
               name:
                 description: This field exists only for technical reasons and should not be set by the user. The value of the field will be overwritten.
@@ -29,7 +29,7 @@ spec:
               benchmark:
                 description: The name of the benchmark this execution is referring to.
                 type: string
-              load: # definition of the load dimension
+              loads: # definition of the load dimension
                 description: Specifies the load values that are benchmarked.
                 type: object
                 required: ["loadType", "loadValues"]
@@ -56,21 +56,15 @@ spec:
                     items:
                       type: integer
               slos: # def of service level objectives
-                description:  List of resource values for the specified resource type.
+                description:  List of SLOs with their properties, which differ from the benchmark definition.
                 type: array
                 items:
                   type: object
-                  required: ["sloType", "prometheusUrl", "offset"]
+                  required: ["name", "properties"]
                   properties:
-                    sloType:
-                      description: The type of the SLO. It must match 'lag trend'.
+                    name:
+                      description: The name of the SLO. It must match a SLO specified in the Benchmark.
                       type: string
-                    prometheusUrl:
-                      description: Connection string for Promehteus.
-                      type: string
-                    offset:
-                      description: Hours by which the start and end timestamp will be shifted (for different timezones).
-                      type: integer
                     properties:
                         description: (Optional) SLO specific additional arguments.
                         type: object
@@ -80,25 +74,35 @@ spec:
               execution: # def execution config
                 description: Defines the overall parameter for the execution.
                 type: object
-                required: ["strategy", "duration", "repetitions", "restrictions"]
+                required: ["strategy", "duration", "repetitions"]
                 properties:
-                  strategy:
-                    description: Defines the used strategy for the execution, either 'LinearSearch' or 'BinarySearch'
+                  metric:
                     type: string
+                  strategy:
+                    description: Defines the used strategy for the execution, either 'LinearSearch', 'BinarySearch' or 'InitialGuessSearch'.
+                    type: object
+                    required: ["name"]
+                    properties:
+                      name:
+                        type: string
+                      restrictions:
+                        description: List of restriction strategies used to delimit the search space.
+                        type: array
+                        items:
+                          type: string
+                      guessStrategy:
+                        type: string
+                      searchStrategy:
+                        type: string
                   duration:
                     description: Defines the duration of each experiment in seconds.
                     type: integer
                   repetitions:
-                    description: Numper of repititions for each experiments.
+                    description: Number of repititions for each experiment.
                     type: integer
                   loadGenerationDelay:
                     description: Seconds to wait between the start of the SUT and the load generator.
                     type: integer
-                  restrictions:
-                    description: List of restriction strategys used to delimit the search space.
-                    type: array
-                    items:
-                      type: string
               configOverrides:
                 description:  List of patchers that are used to override existing configurations.
                 type: array
diff --git a/theodolite/examples/operator/example-benchmark.yaml b/theodolite/examples/operator/example-benchmark.yaml
index 5f68af04750bcd779c9682ede69d6c68b9fb3e92..be7116c46f8222eeba0f3bffd086f7cc2b6ee227 100644
--- a/theodolite/examples/operator/example-benchmark.yaml
+++ b/theodolite/examples/operator/example-benchmark.yaml
@@ -33,8 +33,17 @@ spec:
           resource: "uc1-load-generator-deployment.yaml"
           properties:
             loadGenMaxRecords: "150000"
+  slos:
+    - name: "lag trend"
+      sloType: "lag trend"
+      prometheusUrl: "http://prometheus-operated:9090"
+      offset: 0
+      properties:
+        threshold: 3000
+        externalSloUrl: "http://localhost:80/evaluate-slope"
+        warmup: 60 # in seconds
   kafkaConfig:
-    bootstrapServer: "theodolite-cp-kafka:9092"
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
     topics:
       - name: "input"
         numPartitions: 40
diff --git a/theodolite/examples/operator/example-configmap.yaml b/theodolite/examples/operator/example-configmap.yaml
index 210ce32d3fc0f75b9ffce874d1fa0a1ea9bdc3cd..db511a94cc903869677f2e447d45baf0d983ac6c 100644
--- a/theodolite/examples/operator/example-configmap.yaml
+++ b/theodolite/examples/operator/example-configmap.yaml
@@ -24,7 +24,7 @@ data:
               image: ghcr.io/cau-se/theodolite-uc1-kstreams-app:latest
               env:
                 - name: KAFKA_BOOTSTRAP_SERVERS
-                  value: "theodolite-cp-kafka:9092"
+                  value: "theodolite-kafka-kafka-bootstrap:9092"
                 - name: SCHEMA_REGISTRY_URL
                   value: "http://theodolite-cp-schema-registry:8081"
                 - name: JAVA_OPTS
@@ -65,7 +65,7 @@ data:
                 - name: KUBERNETES_DNS_NAME
                   value: "titan-ccp-load-generator.$(KUBERNETES_NAMESPACE).svc.cluster.local"
                 - name: KAFKA_BOOTSTRAP_SERVERS
-                  value: "theodolite-cp-kafka:9092"
+                  value: "theodolite-kafka-kafka-bootstrap:9092"
                 - name: SCHEMA_REGISTRY_URL
                   value: "http://theodolite-cp-schema-registry:8081"
   uc1-load-generator-service.yaml: |
diff --git a/theodolite/examples/operator/example-execution.yaml b/theodolite/examples/operator/example-execution.yaml
index 576a74b90dfc38483de79502ac14d42f6bedfb49..87e6275a8409177394dd313f2f1f0436e2162577 100644
--- a/theodolite/examples/operator/example-execution.yaml
+++ b/theodolite/examples/operator/example-execution.yaml
@@ -4,27 +4,25 @@ metadata:
   name: theodolite-example-execution
 spec:
   benchmark: "example-benchmark"
-  load:
+  loads:
     loadType: "NumSensors"
     loadValues: [25000, 50000, 75000, 100000, 125000, 150000]
   resources:
     resourceType: "Instances"
     resourceValues: [1, 2, 3, 4, 5]
   slos:
-    - sloType: "lag trend"
-      prometheusUrl: "http://prometheus-operated:9090"
-      offset: 0
+    - name: "lag trend"
       properties:
         threshold: 2000
-        externalSloUrl: "http://localhost:80/evaluate-slope"
-        warmup: 60 # in seconds
   execution:
-    strategy: "LinearSearch"
+    strategy:
+      name: "RestrictionSearch"
+      restrictions:
+        - "LowerBound"
+      searchStrategy: "LinearSearch"
     duration: 300 # in seconds
     repetitions: 1
     loadGenerationDelay: 30 # in seconds
-    restrictions:
-      - "LowerBound"
   configOverrides: []
   # - patcher:
   #     type: "NodeSelectorPatcher"
diff --git a/theodolite/examples/resources/uc1-kstreams-deployment.yaml b/theodolite/examples/resources/uc1-kstreams-deployment.yaml
index fdd1ff867ac83beb10856baec53569c88169232e..1951b1177572dbd1276afcbc6770f91f9f5ff168 100644
--- a/theodolite/examples/resources/uc1-kstreams-deployment.yaml
+++ b/theodolite/examples/resources/uc1-kstreams-deployment.yaml
@@ -21,7 +21,7 @@ spec:
               name: jmx
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
             - name: JAVA_OPTS
diff --git a/theodolite/examples/resources/uc1-load-generator-deployment.yaml b/theodolite/examples/resources/uc1-load-generator-deployment.yaml
index 9f9ccc6ae39407bb1f027e1e23cb152944b869e0..65048a97d5de3d831f782db329e295a5e5ceb727 100644
--- a/theodolite/examples/resources/uc1-load-generator-deployment.yaml
+++ b/theodolite/examples/resources/uc1-load-generator-deployment.yaml
@@ -27,6 +27,6 @@ spec:
             - name: KUBERNETES_DNS_NAME
               value: "titan-ccp-load-generator.$(KUBERNETES_NAMESPACE).svc.cluster.local"
             - name: KAFKA_BOOTSTRAP_SERVERS
-              value: "theodolite-cp-kafka:9092"
+              value: "theodolite-kafka-kafka-bootstrap:9092"
             - name: SCHEMA_REGISTRY_URL
               value: "http://theodolite-cp-schema-registry:8081"
diff --git a/theodolite/examples/standalone/example-benchmark.yaml b/theodolite/examples/standalone/example-benchmark.yaml
index 4d67399231778c91cebb3ffe088e2d26ef388008..254fb4628a595b627f9f4260e3d5478984cec1c6 100644
--- a/theodolite/examples/standalone/example-benchmark.yaml
+++ b/theodolite/examples/standalone/example-benchmark.yaml
@@ -31,7 +31,7 @@ loadTypes:
         properties:
           loadGenMaxRecords: "150000"
 kafkaConfig:
-  bootstrapServer: "theodolite-cp-kafka:9092"
+  bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
   topics:
     - name: "input"
       numPartitions: 40
diff --git a/theodolite/gradle.properties b/theodolite/gradle.properties
index fd5768bc24a65dbd43b3ea770c854ae7c0da0a91..a7c5a39013639072e1ef47f9226b95b513d678d7 100644
--- a/theodolite/gradle.properties
+++ b/theodolite/gradle.properties
@@ -1,8 +1,8 @@
 #Gradle properties
 quarkusPluginId=io.quarkus
-quarkusPluginVersion=2.6.3.Final
+quarkusPluginVersion=2.7.4.Final
 quarkusPlatformGroupId=io.quarkus.platform
 quarkusPlatformArtifactId=quarkus-bom
-quarkusPlatformVersion=2.6.3.Final
+quarkusPlatformVersion=2.7.4.Final
 
 #org.gradle.logging.level=INFO
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/Config.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/Config.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c429d6b3f456c345c7ab2adb1ccd95635603ef4f
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/Config.kt
@@ -0,0 +1,21 @@
+package rocks.theodolite.core
+
+import io.quarkus.runtime.annotations.RegisterForReflection
+import rocks.theodolite.core.strategies.Metric
+import rocks.theodolite.core.strategies.searchstrategy.SearchStrategy
+
+/**
+ * Config class that represents a configuration of a theodolite run.
+ *
+ * @param loads the possible loads of the execution
+ * @param resources the possible resources of the execution
+ * @param searchStrategy the [SearchStrategy] of the execution
+ * @param metric the Metric of the execution
+ */
+@RegisterForReflection
+data class Config(
+        val loads: List<Int>,
+        val resources: List<Int>,
+        val searchStrategy: SearchStrategy,
+        val metric: Metric
+)
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/ExecutionRunner.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/ExecutionRunner.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a63269bb8ebb009ecd858be145523c4029814888
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/ExecutionRunner.kt
@@ -0,0 +1,50 @@
+package rocks.theodolite.core
+
+import rocks.theodolite.core.strategies.Metric
+import rocks.theodolite.core.strategies.searchstrategy.SearchStrategy
+
+
+class ExecutionRunner (private val searchStrategy: SearchStrategy,
+                       private val resources: List<Int>, private val loads: List<Int>,
+                       private val metric: Metric, private val executionId: Int) {
+
+    /**
+     * Run all experiments for given loads and resources.
+     * Called by [rocks.theodolite.kubernetes.execution.TheodoliteExecutor] to run an Execution.
+     */
+    fun run() {
+
+        val ioHandler = IOHandler()
+        val resultsFolder = ioHandler.getResultFolderURL()
+
+        //execute benchmarks for each load for the demand metric, or for each resource amount for capacity metric
+        try {
+            searchStrategy.applySearchStrategyByMetric(loads, resources, metric)
+
+        } finally {
+            ioHandler.writeToJSONFile(
+                    searchStrategy.experimentRunner.results,
+                    "${resultsFolder}exp${executionId}-result"
+            )
+            // Create expXYZ_demand.csv file or expXYZ_capacity.csv depending on metric
+            when(metric) {
+                Metric.DEMAND ->
+                    ioHandler.writeToCSVFile(
+                            "${resultsFolder}exp${executionId}_demand",
+                            calculateMetric(loads, searchStrategy.experimentRunner.results),
+                            listOf("load","resources")
+                    )
+                Metric.CAPACITY ->
+                    ioHandler.writeToCSVFile(
+                            "${resultsFolder}exp${executionId}_capacity",
+                            calculateMetric(resources, searchStrategy.experimentRunner.results),
+                            listOf("resource", "loads")
+                    )
+            }
+        }
+    }
+
+    private fun calculateMetric(xValues: List<Int>, results: Results): List<List<String>> {
+        return xValues.map { listOf(it.toString(), results.getOptYDimensionValue(it).toString()) }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/ExperimentRunner.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/ExperimentRunner.kt
new file mode 100644
index 0000000000000000000000000000000000000000..830469320d98cf66cd9395e3cdf74b2443758c3c
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/ExperimentRunner.kt
@@ -0,0 +1,29 @@
+package rocks.theodolite.core
+
+import java.util.concurrent.atomic.AtomicBoolean
+
+
+/**
+ * Abstract class acts as an interface for the theodolite core to run experiments.
+ * The results of the experiments are stored in [results].
+ *
+ * @property results
+ */
+abstract class ExperimentRunner(val results: Results) {
+
+    var run: AtomicBoolean = AtomicBoolean(true)
+
+    /**
+     * Run an experiment for the given parametrization, evaluate the
+     * experiment and save the result.
+     *
+     * @param load to be tested.
+     * @param resource to be tested.
+     * @return True, if the number of resources are suitable for the
+     *     given load, false otherwise (demand metric), or
+     *     True, if there is a load suitable for the
+     *     given resource, false otherwise.
+     */
+    abstract fun runExperiment(load: Int, resource: Int): Boolean
+
+}
diff --git a/theodolite/src/main/kotlin/theodolite/util/IOHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/IOHandler.kt
similarity index 99%
rename from theodolite/src/main/kotlin/theodolite/util/IOHandler.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/core/IOHandler.kt
index 8b580c733ab7ae527d99c676223f4b09b392c6fd..4d2cab0da938b18950def8cfb5cc6f104e110125 100644
--- a/theodolite/src/main/kotlin/theodolite/util/IOHandler.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/IOHandler.kt
@@ -1,4 +1,4 @@
-package theodolite.util
+package rocks.theodolite.core
 
 import com.google.gson.GsonBuilder
 import mu.KotlinLogging
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/Results.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/Results.kt
new file mode 100644
index 0000000000000000000000000000000000000000..16e6b517e1f570fd17a1b9688aff4f41ec8c9884
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/Results.kt
@@ -0,0 +1,127 @@
+package rocks.theodolite.core
+
+import io.quarkus.runtime.annotations.RegisterForReflection
+import rocks.theodolite.core.strategies.Metric
+
+/**
+ * Central class that saves the state of an execution of Theodolite. For an execution, it is used to save the result of
+ * individual experiments. Further, it is used by the RestrictionStrategy to
+ * perform the [theodolite.strategies.restriction.RestrictionStrategy].
+ */
+@RegisterForReflection
+class Results (val metric: Metric) {
+    // (load, resource) -> Boolean map
+    private val results: MutableMap<Pair<Int, Int>, Boolean> = mutableMapOf()
+
+    // if metric is "demand"  : load     -> resource
+    // if metric is "capacity": resource -> load
+    private var optInstances: MutableMap<Int, Int> = mutableMapOf()
+
+
+    /**
+     * Set the result for an experiment and update the [optInstances] list accordingly.
+     *
+     * @param experiment A pair that identifies the experiment by the Load and Resource.
+     * @param successful the result of the experiment. Successful == true and Unsuccessful == false.
+     */
+    fun setResult(experiment: Pair<Int, Int>, successful: Boolean) {
+        this.results[experiment] = successful
+
+        when (metric) {
+            Metric.DEMAND ->
+                if (successful) {
+                    if (optInstances.containsKey(experiment.first)) {
+                        if (optInstances[experiment.first]!! > experiment.second) {
+                            optInstances[experiment.first] = experiment.second
+                        }
+                    } else {
+                        optInstances[experiment.first] = experiment.second
+                    }
+                } else if (!optInstances.containsKey(experiment.first)) {
+                    optInstances[experiment.first] = Int.MAX_VALUE
+                }
+            Metric.CAPACITY ->
+                if (successful) {
+                    if (optInstances.containsKey(experiment.second)) {
+                        if (optInstances[experiment.second]!! < experiment.first) {
+                            optInstances[experiment.second] = experiment.first
+                        }
+                    } else {
+                        optInstances[experiment.second] = experiment.first
+                    }
+                } else if (!optInstances.containsKey(experiment.second)) {
+                    optInstances[experiment.second] = Int.MIN_VALUE
+                }
+        }
+    }
+
+    /**
+     * Get the result for an experiment.
+     *
+     * @param experiment A pair that identifies the experiment by the Load and Resource.
+     * @return true if the experiment was successful and false otherwise. If the result has not been reported so far,
+     * null is returned.
+     *
+     */
+    fun getResult(experiment: Pair<Int, Int>): Boolean? {
+        return this.results[experiment]
+    }
+
+    /**
+     * Get the smallest suitable number of instances for a specified x-Value.
+     * The x-Value corresponds to the...
+     * - load, if the metric is "demand".
+     * - resource, if the metric is "capacity".
+     *
+     * @param xValue the Value of the x-dimension of the current metric
+     *
+     * @return the smallest suitable number of resources/loads (depending on metric).
+     * If there is no experiment that has been executed yet, there is no experiment
+     * for the given [xValue] or there is none marked successful yet, null is returned.
+     */
+    fun getOptYDimensionValue(xValue: Int?): Int? {
+        if (xValue != null) {
+            val res = optInstances[xValue]
+            if (res != Int.MAX_VALUE && res != Int.MIN_VALUE) {
+                return res
+            }
+        }
+        return null
+    }
+
+    /**
+     * Get the largest x-Value that has been tested and reported so far (successful or unsuccessful),
+     * which is smaller than the specified x-Value.
+     *
+     * The x-Value corresponds to the...
+     * - load, if the metric is "demand".
+     * - resource, if the metric is "capacity".
+     *
+     * @param xValue the Value of the x-dimension of the current metric
+     *
+     * @return the largest tested x-Value or null, if there wasn't any tested which is smaller than the [xValue].
+     */
+    fun getMaxBenchmarkedXDimensionValue(xValue: Int): Int? {
+        var maxBenchmarkedXValue: Int? = null
+        for (instance in optInstances) {
+            val instanceXValue= instance.key
+            if (instanceXValue <= xValue) {
+                if (maxBenchmarkedXValue == null) {
+                    maxBenchmarkedXValue = instanceXValue
+                } else if (maxBenchmarkedXValue < instanceXValue) {
+                    maxBenchmarkedXValue = instanceXValue
+                }
+            }
+        }
+        return maxBenchmarkedXValue
+    }
+
+    /**
+     * Checks whether the results are empty.
+     *
+     * @return true if [results] is empty.
+     */
+    fun isEmpty(): Boolean{
+        return results.isEmpty()
+    }
+}
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/Metric.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/Metric.kt
new file mode 100644
index 0000000000000000000000000000000000000000..db161d10c61fae512e28ba059e604835d22aeb96
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/Metric.kt
@@ -0,0 +1,11 @@
+package rocks.theodolite.core.strategies
+
+enum class Metric(val value: String) {
+    DEMAND("demand"),
+    CAPACITY("capacity");
+
+    companion object {
+        fun from(metric: String): Metric =
+                values().find { it.value == metric } ?: throw IllegalArgumentException("Requested Metric does not exist")
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/StrategyFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/StrategyFactory.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d2925c798e29705f3333130e8c9f09e32d7ec31c
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/StrategyFactory.kt
@@ -0,0 +1,84 @@
+package rocks.theodolite.core.strategies
+
+import rocks.theodolite.core.strategies.guessstrategy.PrevInstanceOptGuess
+import rocks.theodolite.core.strategies.restrictionstrategy.LowerBoundRestriction
+import rocks.theodolite.core.strategies.restrictionstrategy.RestrictionStrategy
+import rocks.theodolite.core.strategies.searchstrategy.*
+import rocks.theodolite.core.ExperimentRunner
+import rocks.theodolite.core.Results
+
+/**
+ * Factory for creating [SearchStrategy] and [RestrictionStrategy] strategies.
+ */
+class StrategyFactory {
+
+    /**
+     * Create a [SearchStrategy].
+     *
+     * @param executor The [theodolite.execution.BenchmarkExecutor] that executes individual experiments.
+     * @param searchStrategyObject Specifies the [SearchStrategy]. Must either be an object with name 'FullSearch',
+     * 'LinearSearch', 'BinarySearch', 'RestrictionSearch' or 'InitialGuessSearch'.
+     * @param results The [Results] saves the state of the Theodolite benchmark run.
+     *
+     * @throws IllegalArgumentException if the [SearchStrategy] was not one of the allowed options.
+     */
+    fun createSearchStrategy(executor: ExperimentRunner, name: String, searchStrategy: String, restrictions: List<String>,
+                             guessStrategy: String, results: Results): SearchStrategy {
+
+        var strategy : SearchStrategy = when (name) {
+            "FullSearch" -> FullSearch(executor)
+            "LinearSearch" -> LinearSearch(executor)
+            "BinarySearch" -> BinarySearch(executor)
+            "RestrictionSearch" -> when (searchStrategy){
+                "FullSearch" -> composeSearchRestrictionStrategy(executor, FullSearch(executor), results, restrictions)
+                "LinearSearch" -> composeSearchRestrictionStrategy(executor, LinearSearch(executor), results, restrictions)
+                "BinarySearch" -> composeSearchRestrictionStrategy(executor, BinarySearch(executor), results, restrictions)
+                else -> throw IllegalArgumentException("Search Strategy $searchStrategy for RestrictionSearch not found")
+            }
+            "InitialGuessSearch" -> when (guessStrategy){
+                "PrevResourceMinGuess" -> InitialGuessSearchStrategy(executor, PrevInstanceOptGuess(), results)
+                else -> throw IllegalArgumentException("Guess Strategy $guessStrategy not found")
+            }
+            else -> throw IllegalArgumentException("Search Strategy not found")
+        }
+
+        return strategy
+    }
+
+    /**
+     * Create a [RestrictionStrategy].
+     *
+     * @param results The [Results] saves the state of the Theodolite benchmark run.
+     * @param restrictionStrings Specifies the list of [RestrictionStrategy] that are used to restrict the amount
+     * of Resource for a fixed load or resource (depending on the metric).
+     * Must equal the string 'LowerBound'.
+     *
+     * @throws IllegalArgumentException if param searchStrategyString was not one of the allowed options.
+     */
+    private fun createRestrictionStrategy(results: Results, restrictionStrings: List<String>): Set<RestrictionStrategy> {
+        return restrictionStrings
+            .map { restriction ->
+                when (restriction) {
+                    "LowerBound" -> LowerBoundRestriction(results)
+                    else -> throw IllegalArgumentException("Restriction Strategy $restrictionStrings not found")
+                }
+            }.toSet()
+    }
+
+    /**
+     * Create a RestrictionSearch, if the provided restriction list is not empty. Otherwise just return the given
+     * searchStrategy.
+     *
+     * @param executor The [theodolite.execution.BenchmarkExecutor] that executes individual experiments.
+     * @param searchStrategy The [SearchStrategy] to use.
+     * @param results The [Results] saves the state of the Theodolite benchmark run.
+     * @param restrictions The [RestrictionStrategy]'s to use.
+     */
+    private fun composeSearchRestrictionStrategy(executor: ExperimentRunner, searchStrategy: SearchStrategy,
+                                                 results: Results, restrictions: List<String>): SearchStrategy {
+        if(restrictions.isNotEmpty()){
+            return RestrictionSearch(executor,searchStrategy,createRestrictionStrategy(results, restrictions))
+        }
+        return searchStrategy
+    }
+}
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/guessstrategy/GuessStrategy.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/guessstrategy/GuessStrategy.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6ab5c1b6d10da318c4b5b3f24d6cc521ff247e79
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/guessstrategy/GuessStrategy.kt
@@ -0,0 +1,22 @@
+package rocks.theodolite.core.strategies.guessstrategy
+
+import io.quarkus.runtime.annotations.RegisterForReflection
+
+/**
+ * Base class for the implementation of Guess strategies. Guess strategies are strategies to determine the resource
+ * demand (demand metric) or load (capacity metric) we start with in our initial guess search strategy.
+ */
+
+@RegisterForReflection
+abstract class GuessStrategy {
+    /**
+     * Computing the resource demand (demand metric) or load (capacity metric) for the initial guess search strategy
+     * to start with.
+     *
+     * @param valuesToCheck List of all possible resources/loads.
+     * @param lastOptValue Previous minimal/maximal resource/load value for the given load/resource.
+     *
+     * @return the resource/load to start the initial guess search strategy with or null
+     */
+    abstract fun firstGuess(valuesToCheck: List<Int>, lastOptValue: Int?): Int?
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/guessstrategy/PrevInstanceOptGuess.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/guessstrategy/PrevInstanceOptGuess.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3b2d7b1b0e6c4133b939742a83afc55fabb7b101
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/guessstrategy/PrevInstanceOptGuess.kt
@@ -0,0 +1,28 @@
+package rocks.theodolite.core.strategies.guessstrategy
+
+
+/**
+ * [PrevInstanceOptGuess] is a [GuessStrategy] that implements the function [firstGuess],
+ * where it returns the optimal result of the previous run.
+ */
+
+class PrevInstanceOptGuess() : GuessStrategy(){
+
+    /**
+     * If the metric is
+     *
+     * - "demand", [valuesToCheck] is a List of resources and [lastOptValue] a resource value.
+     * - "capacity", [valuesToCheck] is a List of loads and [lastOptValue] a load value.
+     *
+     * @param valuesToCheck List of all possible resources/loads.
+     * @param lastOptValue Previous minimal/maximal resource/load value for the given load/resource.
+     *
+     * @return the value of [lastOptValue] if given otherwise the first element of the [valuesToCheck] list or null
+     */
+    override fun firstGuess(valuesToCheck: List<Int>, lastOptValue: Int?): Int? {
+
+        if (lastOptValue != null) return lastOptValue
+        else if(valuesToCheck.isNotEmpty()) return valuesToCheck[0]
+        else return null
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/LowerBoundRestriction.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/LowerBoundRestriction.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2e5a51018fd742abbb18edb1d788a6644e94d2f1
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/LowerBoundRestriction.kt
@@ -0,0 +1,24 @@
+package rocks.theodolite.core.strategies.restrictionstrategy
+
+import rocks.theodolite.core.Results
+
+/**
+ * The [LowerBoundRestriction] sets the lower bound of the resources to be examined in the experiment to the value
+ * needed to successfully execute the previous smaller load (demand metric), or sets the lower bound of the loads
+ * to be examined in the experiment to the largest value, which still successfully executed the previous smaller
+ * resource (capacity metric).
+ *
+ * @param results [Result] object used as a basis to restrict the resources.
+ */
+class LowerBoundRestriction(results: Results) : RestrictionStrategy(results) {
+
+    override fun apply(xValue: Int, yValues: List<Int>): List<Int> {
+        val maxXValue: Int? = this.results.getMaxBenchmarkedXDimensionValue(xValue)
+        var lowerBound: Int? = this.results.getOptYDimensionValue(maxXValue)
+        if (lowerBound == null) {
+            lowerBound = yValues[0]
+        }
+        return yValues.filter { x -> x >= lowerBound }
+    }
+
+}
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/RestrictionStrategy.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/RestrictionStrategy.kt
new file mode 100644
index 0000000000000000000000000000000000000000..16532c32e2c9c64ac69d1c5ed32f6ec0d3345747
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/RestrictionStrategy.kt
@@ -0,0 +1,24 @@
+package rocks.theodolite.core.strategies.restrictionstrategy
+
+import io.quarkus.runtime.annotations.RegisterForReflection
+import rocks.theodolite.core.Results
+
+/**
+ * A 'Restriction Strategy' restricts a list of resources or loads depending on the metric based on the current
+ * results of all previously performed benchmarks.
+ *
+ * @param results the [Results] object
+ */
+@RegisterForReflection
+abstract class RestrictionStrategy(val results: Results) {
+    /**
+     * Apply the restriction of the given resource list for the given load based on the results object (demand metric),
+     * or apply the restriction of the given load list for the given resource based on the results object (capacity metric).
+     *
+     * @param xValue The value to be examined in the experiment, can be load (demand metric) or resource (capacity metric).
+     * @param yValues List of values to be restricted, can be resources (demand metric) or loads (capacity metric).
+     * @return Returns a list containing only elements that have not been filtered out by the
+     * restriction (possibly empty).
+     */
+    abstract fun apply(xValue: Int, yValues: List<Int>): List<Int>
+}
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/BinarySearch.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/BinarySearch.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7c339c449e85a0fa73484d60a455016931cee473
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/BinarySearch.kt
@@ -0,0 +1,108 @@
+package rocks.theodolite.core.strategies.searchstrategy
+
+import mu.KotlinLogging
+import rocks.theodolite.core.ExperimentRunner
+
+private val logger = KotlinLogging.logger {}
+
+/**
+ *  Binary-search-like implementation for determining the smallest suitable number of instances.
+ *
+ * @param experimentRunner Benchmark executor which runs the individual benchmarks.
+ */
+class BinarySearch(experimentRunner: ExperimentRunner) : SearchStrategy(experimentRunner) {
+    override fun findSuitableResource(load: Int, resources: List<Int>): Int? {
+        val result = binarySearchDemand(load, resources, 0, resources.size - 1)
+        if (result == -1) {
+            return null
+        }
+        return resources[result]
+    }
+
+    override fun findSuitableLoad(resource: Int, loads: List<Int>): Int? {
+        val result = binarySearchCapacity(resource, loads, 0, loads.size - 1)
+        if (result == -1) {
+            return null
+        }
+        return loads[result]
+    }
+
+    /**
+     * Apply binary search for the demand metric.
+     *
+     * @param load the load to perform experiments for.
+     * @param resources the list of resources in which binary search is performed.
+     * @param lower lower bound for binary search (inclusive).
+     * @param upper upper bound for binary search (inclusive).
+     */
+    private fun binarySearchDemand(load: Int, resources: List<Int>, lower: Int, upper: Int): Int {
+        if (lower > upper) {
+            throw IllegalArgumentException()
+        }
+        // special case:  length == 1, so lower and upper bounds are the same
+        if (lower == upper) {
+            val res = resources[lower]
+            logger.info { "Running experiment with load '$load' and resource '$res'" }
+            if (this.experimentRunner.runExperiment(load, res)) return lower
+            else {
+                if (lower + 1 == resources.size) return -1
+                return lower + 1
+            }
+        } else {
+            // apply binary search for a list with
+            // length >= 2 and adjust upper and lower depending on the result for `resources[mid]`
+            val mid = (upper + lower) / 2
+            val res = resources[mid]
+            logger.info { "Running experiment with load '$load' and resource '$res'" }
+            if (this.experimentRunner.runExperiment(load, res)) {
+                // case length = 2
+                if (mid == lower) {
+                    return lower
+                }
+                return binarySearchDemand(load, resources, lower, mid - 1)
+            } else {
+                return binarySearchDemand(load, resources, mid + 1, upper)
+            }
+        }
+    }
+
+
+    /**
+     * Apply binary search for the capacity metric.
+     *
+     * @param resource the resource to perform experiments for.
+     * @param loads the list of loads in which binary search is performed.
+     * @param lower lower bound for binary search (inclusive).
+     * @param upper upper bound for binary search (inclusive).
+     */
+    private fun binarySearchCapacity(resource: Int, loads: List<Int>, lower: Int, upper: Int): Int {
+        if (lower > upper) {
+            throw IllegalArgumentException()
+        }
+        // length = 1, so lower and upper bounds are the same
+        if (lower == upper) {
+            val load = loads[lower]
+            logger.info { "Running experiment with load '$load' and resource '$resource'" }
+            if (this.experimentRunner.runExperiment(load, resource)) return lower
+            else {
+                if (lower + 1 == loads.size) return -1
+                return lower - 1
+            }
+        } else {
+            // apply binary search for a list with
+            // length > 2 and adjust upper and lower depending on the result for `resources[mid]`
+            val mid = (upper + lower + 1) / 2 //round to next int
+            val load = loads[mid]
+            logger.info { "Running experiment with load '$load' and resource '$resource'" }
+            if (this.experimentRunner.runExperiment(load, resource)) {
+                // length = 2, so since we round down mid is equal to lower
+                if (mid == upper) {
+                    return upper
+                }
+                return binarySearchCapacity(resource, loads, mid + 1, upper)
+            } else {
+                return binarySearchCapacity(resource, loads, lower, mid - 1)
+            }
+        }
+    }
+}
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/FullSearch.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/FullSearch.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7cd1dfe08cfef7ea42f0a663bbc80eb63f8ca9fe
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/FullSearch.kt
@@ -0,0 +1,39 @@
+package rocks.theodolite.core.strategies.searchstrategy
+
+import mu.KotlinLogging
+import rocks.theodolite.core.ExperimentRunner
+
+private val logger = KotlinLogging.logger {}
+
+/**
+ * [SearchStrategy] that executes an experiment for a load and a resource list (demand metric) or for a resource and a
+ * load list (capacity metric) in a linear-search-like fashion, but **without stopping** once the desired
+ * resource (demand) or load (capacity) is found.
+ *
+ * @see LinearSearch for a SearchStrategy that stops once the desired resource (demand) or load (capacity) is found.
+ *
+ * @param experimentRunner Benchmark executor which runs the individual benchmarks.
+ */
+class FullSearch(experimentRunner: ExperimentRunner) : SearchStrategy(experimentRunner) {
+
+    override fun findSuitableResource(load: Int, resources: List<Int>): Int? {
+        var minimalSuitableResources: Int? = null
+        for (res in resources) {
+            logger.info { "Running experiment with load '$load' and resources '$res'" }
+            val result = this.experimentRunner.runExperiment(load, res)
+            if (result && minimalSuitableResources == null) {
+                minimalSuitableResources = res
+            }
+        }
+        return minimalSuitableResources
+    }
+
+    override fun findSuitableLoad(resource: Int, loads: List<Int>): Int? {
+        var maxSuitableLoad: Int? = null
+        for (load in loads) {
+            logger.info { "Running experiment with resources '$resource' and load '$load'" }
+            if (this.experimentRunner.runExperiment(load, resource)) maxSuitableLoad = load
+        }
+        return maxSuitableLoad
+    }
+}
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/InitialGuessSearchStrategy.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/InitialGuessSearchStrategy.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8d257bb329729cab033e10195e7a9df3260aeeb3
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/InitialGuessSearchStrategy.kt
@@ -0,0 +1,133 @@
+package rocks.theodolite.core.strategies.searchstrategy
+
+import mu.KotlinLogging
+import rocks.theodolite.core.strategies.guessstrategy.GuessStrategy
+import rocks.theodolite.core.ExperimentRunner
+import rocks.theodolite.core.Results
+
+private val logger = KotlinLogging.logger {}
+
+/**
+ *  Search strategy implementation for determining the smallest suitable resource demand.
+ *  Starting with a resource amount provided by a guess strategy.
+ *
+ * @param experimentRunner Benchmark executor which runs the individual benchmarks.
+ * @param guessStrategy Strategy that provides us with a guess for the first resource amount.
+ * @param results current results of all previously performed benchmarks.
+ */
+class InitialGuessSearchStrategy(
+        experimentRunner: ExperimentRunner,
+        private val guessStrategy: GuessStrategy,
+        private var results: Results
+) : SearchStrategy(experimentRunner) {
+
+    override fun findSuitableResource(load: Int, resources: List<Int>): Int? {
+
+        var lastLowestResource : Int? = null
+
+        // Getting the lastLowestResource from results and calling firstGuess() with it
+        if (!results.isEmpty()) {
+            val maxLoad: Int? = this.results.getMaxBenchmarkedXDimensionValue(load)
+            lastLowestResource = this.results.getOptYDimensionValue(maxLoad)
+        }
+        lastLowestResource = this.guessStrategy.firstGuess(resources, lastLowestResource)
+
+        if (lastLowestResource != null) {
+            val resourcesToCheck: List<Int>
+            val startIndex: Int = resources.indexOf(lastLowestResource)
+
+            logger.info { "Running experiment with load '$load' and resources '$lastLowestResource'" }
+
+            // If the first experiment passes, starting downward linear search
+            // otherwise starting upward linear search
+            if (this.experimentRunner.runExperiment(load, lastLowestResource)) {
+
+                resourcesToCheck = resources.subList(0, startIndex).reversed()
+                if (resourcesToCheck.isEmpty()) return lastLowestResource
+
+                var currentMin: Int = lastLowestResource
+                for (res in resourcesToCheck) {
+
+                    logger.info { "Running experiment with load '$load' and resources '$res'" }
+                    if (this.experimentRunner.runExperiment(load, res)) {
+                        currentMin = res
+                    }
+                }
+                return currentMin
+            }
+            else {
+                if (resources.size <= startIndex + 1) {
+                    logger.info{ "No more resources left to check." }
+                    return null
+                }
+                resourcesToCheck = resources.subList(startIndex + 1, resources.size)
+
+                for (res in resourcesToCheck) {
+
+                    logger.info { "Running experiment with load '$load' and resources '$res'" }
+                    if (this.experimentRunner.runExperiment(load, res)) return res
+                }
+            }
+        }
+        else {
+            logger.info { "lastLowestResource was null." }
+        }
+        return null
+    }
+
+    override fun findSuitableLoad(resource: Int, loads: List<Int>): Int?{
+
+        var lastMaxLoad : Int? = null
+
+        // Getting the lastLowestLoad from results and calling firstGuess() with it
+        if (!results.isEmpty()) {
+            val maxResource: Int? = this.results.getMaxBenchmarkedXDimensionValue(resource)
+            lastMaxLoad = this.results.getOptYDimensionValue(maxResource)
+        }
+        lastMaxLoad = this.guessStrategy.firstGuess(loads, lastMaxLoad)
+
+        if (lastMaxLoad != null) {
+            val loadsToCheck: List<Int>
+            val startIndex: Int = loads.indexOf(lastMaxLoad)
+
+            logger.info { "Running experiment with resource '$resource' and load '$lastMaxLoad'" }
+
+            // If the first experiment passes, starting upwards linear search
+            // otherwise starting downward linear search
+            if (!this.experimentRunner.runExperiment(lastMaxLoad, resource)) {
+                // downward search
+
+                loadsToCheck = loads.subList(0, startIndex).reversed()
+                if (loadsToCheck.isNotEmpty()) {
+                    for (load in loadsToCheck) {
+
+                        logger.info { "Running experiment with resource '$resource' and load '$load'" }
+                        if (this.experimentRunner.runExperiment(load, resource)) {
+                            return load
+                        }
+                    }
+                }
+            }
+            else {
+                // upward search
+                if (loads.size <= startIndex + 1) {
+                    return lastMaxLoad
+                }
+                loadsToCheck = loads.subList(startIndex + 1, loads.size)
+
+                var currentMax: Int = lastMaxLoad
+                for (load in loadsToCheck) {
+                    logger.info { "Running experiment with resource '$resource' and load '$load'" }
+                    if (this.experimentRunner.runExperiment(load, resource)) {
+                        currentMax = load
+                    }
+                }
+                return currentMax
+            }
+        }
+        else {
+            logger.info { "lastMaxLoad was null." }
+        }
+        return null
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/LinearSearch.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/LinearSearch.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c3276f05e141d15652012952991a47a1fde30ad4
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/LinearSearch.kt
@@ -0,0 +1,34 @@
+package rocks.theodolite.core.strategies.searchstrategy
+
+import mu.KotlinLogging
+import rocks.theodolite.core.ExperimentRunner
+
+private val logger = KotlinLogging.logger {}
+
+/**
+ *  Linear-search-like implementation for determining the smallest/biggest suitable number of resources/loads,
+ *  depending on the metric.
+ *
+ * @param experimentRunner Benchmark executor which runs the individual benchmarks.
+ */
+class LinearSearch(experimentRunner: ExperimentRunner) : SearchStrategy(experimentRunner) {
+
+    override fun findSuitableResource(load: Int, resources: List<Int>): Int? {
+        for (res in resources) {
+            logger.info { "Running experiment with load '$load' and resources '$res'" }
+            if (this.experimentRunner.runExperiment(load, res)) return res
+        }
+        return null
+    }
+
+    override fun findSuitableLoad(resource: Int, loads: List<Int>): Int? {
+        var maxSuitableLoad: Int? = null
+        for (load in loads) {
+            logger.info { "Running experiment with resources '$resource' and load '$load'" }
+            if (this.experimentRunner.runExperiment(load, resource)) {
+                maxSuitableLoad = load
+            } else break
+        }
+        return maxSuitableLoad
+    }
+}
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/RestrictionSearch.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/RestrictionSearch.kt
new file mode 100644
index 0000000000000000000000000000000000000000..703a7de8b9e084b2bb55bc9270b9d07ea6adfe83
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/RestrictionSearch.kt
@@ -0,0 +1,43 @@
+package rocks.theodolite.core.strategies.searchstrategy
+
+import io.quarkus.runtime.annotations.RegisterForReflection
+import rocks.theodolite.core.strategies.restrictionstrategy.RestrictionStrategy
+import rocks.theodolite.core.ExperimentRunner
+
+/**
+ *  Strategy that combines a SearchStrategy and a set of RestrictionStrategy.
+ *
+ * @param experimentRunner Benchmark executor which runs the individual benchmarks.
+ * @param searchStrategy the [SearchStrategy] that is executed as part of this [RestrictionSearch].
+ * @param restrictionStrategies the set of [RestrictionStrategy] that are connected conjunctive to restrict the Resource.
+ *
+ */
+@RegisterForReflection
+class RestrictionSearch(
+        experimentRunner: ExperimentRunner,
+        private val searchStrategy: SearchStrategy,
+        private val restrictionStrategies: Set<RestrictionStrategy>
+) : SearchStrategy(experimentRunner) {
+
+    /**
+     * Restricting the possible resources and calling findSuitableResource of the given [SearchStrategy].
+     */
+    override fun findSuitableResource(load: Int, resources: List<Int>): Int? {
+        var restrictedResources = resources
+        for (strategy in this.restrictionStrategies) {
+            restrictedResources = restrictedResources.intersect(strategy.apply(load, resources).toSet()).toList()
+        }
+        return this.searchStrategy.findSuitableResource(load, restrictedResources)
+    }
+
+    /**
+     * Restricting the possible loads and calling findSuitableLoad of the given [SearchStrategy].
+     */
+    override fun findSuitableLoad(resource: Int, loads: List<Int>): Int? {
+        var restrictedLoads = loads
+        for (strategy in this.restrictionStrategies) {
+            restrictedLoads = restrictedLoads.intersect(strategy.apply(resource, loads).toSet()).toList()
+        }
+        return this.searchStrategy.findSuitableLoad(resource, restrictedLoads)
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/SearchStrategy.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/SearchStrategy.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d08581ff70c509f54a9b8e5f972bb3661cb0b8f8
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/SearchStrategy.kt
@@ -0,0 +1,63 @@
+package rocks.theodolite.core.strategies.searchstrategy
+
+import io.quarkus.runtime.annotations.RegisterForReflection
+import rocks.theodolite.core.strategies.Metric
+import rocks.theodolite.core.ExperimentRunner
+
+/**
+ *  Base class for the implementation for SearchStrategies. SearchStrategies determine the smallest suitable number
+ *  of resources/loads for a load/resource (depending on the metric).
+ *
+ * @param experimentRunner Benchmark executor which runs the individual benchmarks.
+ * @param guessStrategy Guess strategy for the initial resource amount in case the InitialGuessStrategy is selected.
+ * @param results the [Results] object.
+ */
+@RegisterForReflection
+abstract class SearchStrategy(val experimentRunner: ExperimentRunner) {
+
+
+    /**
+     * Calling findSuitableResource or findSuitableLoad for each load/resource depending on the chosen metric.
+     *
+     * @param loads List of possible loads for the experiments.
+     * @param resources List of possible resources for the experiments.
+     * @param metric The [Metric] for the experiments, either "demand" or "capacity".
+     */
+    fun applySearchStrategyByMetric(loads: List<Int>, resources: List<Int>, metric: Metric) {
+
+        when(metric) {
+            Metric.DEMAND ->
+                for (load in loads) {
+                    if (experimentRunner.run.get()) {
+                        this.findSuitableResource(load, resources)
+                    }
+                }
+            Metric.CAPACITY ->
+                for (resource in resources) {
+                    if (experimentRunner.run.get()) {
+                        this.findSuitableLoad(resource, loads)
+                    }
+                }
+        }
+    }
+
+    /**
+     * Find the smallest suitable resource from the specified resource list for the given load.
+     *
+     * @param load the load to be tested.
+     * @param resources List of all possible resources.
+     *
+     * @return suitable resource for the specified load, or null if no suitable resource exists.
+     */
+    abstract fun findSuitableResource(load: Int, resources: List<Int>): Int?
+
+    /**
+     * Find the biggest suitable load from the specified load list for the given resource amount.
+     *
+     * @param resource the resource to be tested.
+     * @param loads List of all possible loads.
+     *
+     * @return suitable load for the specified resource amount, or null if no suitable load exists.
+     */
+    abstract fun findSuitableLoad(resource: Int, loads: List<Int>) : Int?
+}
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/Action.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Action.kt
similarity index 85%
rename from theodolite/src/main/kotlin/theodolite/benchmark/Action.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Action.kt
index 35efebdc0fb2a3748660cb76cdd5499b4ca5f622..2ecf486323f0ed1e71be1fe069d93dc81edddc65 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/Action.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Action.kt
@@ -1,11 +1,10 @@
-package theodolite.benchmark
+package rocks.theodolite.kubernetes
 
 import com.fasterxml.jackson.annotation.JsonInclude
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.quarkus.runtime.annotations.RegisterForReflection
-import theodolite.util.ActionCommandFailedException
-import theodolite.util.Configuration
+
 
 @JsonDeserialize
 @RegisterForReflection
@@ -23,7 +22,7 @@ class Action {
                 timeout = exec.timeoutSeconds,
                 command = exec.command
         )
-            if(exitCode != 0){
+        if (exitCode != 0){
             throw ActionCommandFailedException("Error while executing action, finished with exit code $exitCode")
         }
     }
@@ -38,7 +37,7 @@ class ActionSelector {
 @JsonDeserialize
 @RegisterForReflection
 class PodSelector {
-    lateinit var matchLabels: MutableMap<String, String>
+    lateinit var matchLabels: Map<String, String>
 }
 @JsonDeserialize
 @RegisterForReflection
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ActionCommand.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ActionCommand.kt
similarity index 90%
rename from theodolite/src/main/kotlin/theodolite/benchmark/ActionCommand.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ActionCommand.kt
index 966fa56329c8d7d466dd14858bcbc06bb5b857c3..eefacbea9268f44969fd88d7650d5ddc5e00fb8e 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/ActionCommand.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ActionCommand.kt
@@ -1,4 +1,4 @@
-package theodolite.benchmark
+package rocks.theodolite.kubernetes
 
 import io.fabric8.kubernetes.api.model.Status
 import io.fabric8.kubernetes.client.KubernetesClientException
@@ -7,9 +7,6 @@ import io.fabric8.kubernetes.client.dsl.ExecListener
 import io.fabric8.kubernetes.client.dsl.ExecWatch
 import io.fabric8.kubernetes.client.utils.Serialization
 import mu.KotlinLogging
-import okhttp3.Response
-import theodolite.util.ActionCommandFailedException
-import theodolite.util.Configuration
 import java.io.ByteArrayOutputStream
 import java.time.Duration
 import java.util.concurrent.CountDownLatch
@@ -34,7 +31,7 @@ class ActionCommand(val client: NamespacedKubernetesClient) {
      * @return the exit code of this executed command
      */
     fun exec(
-        matchLabels: MutableMap<String, String>,
+        matchLabels: Map<String, String>,
         command: Array<String>,
         timeout: Long = Configuration.TIMEOUT_SECONDS,
         container: String = ""
@@ -59,7 +56,7 @@ class ActionCommand(val client: NamespacedKubernetesClient) {
 
             val latchTerminationStatus = execLatch.await(timeout, TimeUnit.SECONDS)
             if (!latchTerminationStatus) {
-                throw ActionCommandFailedException("Latch could not terminate within specified time")
+                throw ActionCommandFailedException("Timeout while running action command")
             }
             execWatch.close()
         } catch (e: Exception) {
@@ -113,7 +110,7 @@ class ActionCommand(val client: NamespacedKubernetesClient) {
      * it can take a while until the status is ready and the pod can be selected.
      * @return the name of the pod or throws [ActionCommandFailedException]
      */
-    fun getPodName(matchLabels: MutableMap<String, String>, tries: Int): String {
+    fun getPodName(matchLabels: Map<String, String>, tries: Int): String {
         for (i in 1..tries) {
 
             try {
@@ -126,7 +123,7 @@ class ActionCommand(val client: NamespacedKubernetesClient) {
         throw ActionCommandFailedException("Couldn't find any pod that matches the specified labels.")
     }
 
-    private fun getPodName(matchLabels: MutableMap<String, String>): String {
+    private fun getPodName(matchLabels: Map<String, String>): String {
         return try {
             val podNames = this.client
                 .pods()
@@ -145,10 +142,8 @@ class ActionCommand(val client: NamespacedKubernetesClient) {
     }
 
     private class ActionCommandListener(val execLatch: CountDownLatch) : ExecListener {
-        override fun onOpen(response: Response) {
-        }
 
-        override fun onFailure(throwable: Throwable, response: Response) {
+        override fun onFailure(throwable: Throwable, response: ExecListener.Response) {
             execLatch.countDown()
             throw ActionCommandFailedException("Some error encountered while executing action, caused ${throwable.message})")
         }
diff --git a/theodolite/src/main/kotlin/theodolite/util/ActionCommandFailedException.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ActionCommandFailedException.kt
similarity index 76%
rename from theodolite/src/main/kotlin/theodolite/util/ActionCommandFailedException.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ActionCommandFailedException.kt
index c1a8fc401961370d2f07bfffe43f0ae4dc441d25..8472b0cc9b46a952dbeb14eb73093c821cd6ed57 100644
--- a/theodolite/src/main/kotlin/theodolite/util/ActionCommandFailedException.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ActionCommandFailedException.kt
@@ -1,4 +1,4 @@
-package theodolite.util
+package rocks.theodolite.kubernetes
 
 class ActionCommandFailedException(message: String, e: Exception? = null) : DeploymentFailedException(message,e) {
 }
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkDeployment.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/BenchmarkDeployment.kt
similarity index 93%
rename from theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkDeployment.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/BenchmarkDeployment.kt
index fd01ecd986775ef704949743fef0d19f5492e9a6..df303b3b85175d6133e8bc9e7a2748cf8c46464c 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkDeployment.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/BenchmarkDeployment.kt
@@ -1,4 +1,4 @@
-package theodolite.benchmark
+package rocks.theodolite.kubernetes
 
 /**
  *  A BenchmarkDeployment contains the necessary infrastructure to execute a benchmark.
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/BenchmarkDeploymentBuilder.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/BenchmarkDeploymentBuilder.kt
new file mode 100644
index 0000000000000000000000000000000000000000..544f8bd5ae227ca682e688dff9fc9df0efec60c3
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/BenchmarkDeploymentBuilder.kt
@@ -0,0 +1,25 @@
+package rocks.theodolite.kubernetes
+
+import rocks.theodolite.kubernetes.patcher.PatcherDefinition
+import rocks.theodolite.kubernetes.util.ConfigurationOverride
+
+/**
+ * This interface is needed for test purposes.
+ */
+interface BenchmarkDeploymentBuilder {
+
+    /**
+     * Builds a Deployment that can be deployed.
+     * @return a BenchmarkDeployment.
+     */
+    fun buildDeployment(
+        load: Int,
+        loadPatcherDefinitions: List<PatcherDefinition>,
+        resource: Int,
+        resourcePatcherDefinitions: List<PatcherDefinition>,
+        configurationOverrides: List<ConfigurationOverride?>,
+        loadGenerationDelay: Long,
+        afterTeardownDelay: Long,
+        waitForResourcesEnabled: Boolean
+    ): BenchmarkDeployment
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ConfigMapResourceSet.kt
similarity index 56%
rename from theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ConfigMapResourceSet.kt
index f85b83497e5d69e43c1d4784ef86170a5436e929..43c478b983d879135b00e6208df8bb36b7978c8f 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ConfigMapResourceSet.kt
@@ -1,23 +1,20 @@
-package theodolite.benchmark
+package rocks.theodolite.kubernetes
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+import io.fabric8.kubernetes.api.model.HasMetadata
 import io.fabric8.kubernetes.api.model.KubernetesResource
 import io.fabric8.kubernetes.client.KubernetesClientException
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.quarkus.runtime.annotations.RegisterForReflection
-import theodolite.k8s.resourceLoader.K8sResourceLoaderFromString
-import theodolite.util.DeploymentFailedException
-import theodolite.util.YamlParserFromString
 import java.lang.IllegalArgumentException
 
 @RegisterForReflection
 @JsonDeserialize
 class ConfigMapResourceSet : ResourceSet, KubernetesResource {
     lateinit var name: String
-    lateinit var files: List<String> // load all files, iff files is not set
+    var files: List<String>? = null // load all files, iff files is not set
 
-    override fun getResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, KubernetesResource>> {
-        val loader = K8sResourceLoaderFromString(client)
+    override fun getResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, HasMetadata>> {
         var resources: Map<String, String>
 
         try {
@@ -31,9 +28,9 @@ class ConfigMapResourceSet : ResourceSet, KubernetesResource {
             throw DeploymentFailedException("Cannot find or read ConfigMap with name '$name'.", e)
         }
 
-        if (::files.isInitialized) {
-            val filteredResources = resources.filter { files.contains(it.key) }
-            if (filteredResources.size != files.size) {
+        files?.run {
+            val filteredResources = resources.filter { this.contains(it.key) }
+            if (filteredResources.size != this.size) {
                 throw DeploymentFailedException("Could not find all specified Kubernetes manifests files")
             }
             resources = filteredResources
@@ -43,14 +40,8 @@ class ConfigMapResourceSet : ResourceSet, KubernetesResource {
             resources
                 .map {
                     Pair(
-                        getKind(resource = it.value),
-                        it
-                    )
-                }
-                .map {
-                    Pair(
-                        it.second.key,
-                        loader.loadK8sResource(it.first, it.second.value)
+                        it.key, // filename
+                        client.resource(it.value).get()
                     )
                 }
         } catch (e: IllegalArgumentException) {
@@ -59,11 +50,4 @@ class ConfigMapResourceSet : ResourceSet, KubernetesResource {
 
     }
 
-    private fun getKind(resource: String): String {
-        val parser = YamlParserFromString()
-        val resourceAsMap = parser.parse(resource, HashMap<String, String>()::class.java)
-
-        return resourceAsMap?.get("kind")
-            ?: throw DeploymentFailedException("Could not find field kind of Kubernetes resource: ${resourceAsMap?.get("name")}")
-    }
 }
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/util/Configuration.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Configuration.kt
similarity index 90%
rename from theodolite/src/main/kotlin/theodolite/util/Configuration.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Configuration.kt
index 0a63cfa84de9e60fba04707372ef884d77a1543b..e28e2a2a7644222f656bdebd05d122cd853ac456 100644
--- a/theodolite/src/main/kotlin/theodolite/util/Configuration.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Configuration.kt
@@ -1,6 +1,4 @@
-package theodolite.util
-
-import theodolite.execution.ExecutionModes
+package rocks.theodolite.kubernetes
 
 // Defaults
 private const val DEFAULT_NAMESPACE = "default"
diff --git a/theodolite/src/main/kotlin/theodolite/util/DeploymentFailedException.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/DeploymentFailedException.kt
similarity index 75%
rename from theodolite/src/main/kotlin/theodolite/util/DeploymentFailedException.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/DeploymentFailedException.kt
index 9f4caedf3db1e09dca7924bf0035c6ace0b835d7..cde0021255b471354e8513139cad0f6e083f804a 100644
--- a/theodolite/src/main/kotlin/theodolite/util/DeploymentFailedException.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/DeploymentFailedException.kt
@@ -1,4 +1,4 @@
-package theodolite.util
+package rocks.theodolite.kubernetes
 
 
 open class DeploymentFailedException(message: String, e: Exception? = null) : TheodoliteException(message,e)
diff --git a/theodolite/src/main/kotlin/theodolite/util/ExecutionFailedException.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecutionFailedException.kt
similarity index 75%
rename from theodolite/src/main/kotlin/theodolite/util/ExecutionFailedException.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecutionFailedException.kt
index 2e181dad35786d386226f8a57dfffbc2c3966754..8924dd18199e0ff937c783873878c6f245d01ea5 100644
--- a/theodolite/src/main/kotlin/theodolite/util/ExecutionFailedException.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecutionFailedException.kt
@@ -1,3 +1,3 @@
-package theodolite.util
+package rocks.theodolite.kubernetes
 
 open class ExecutionFailedException(message: String, e: Exception? = null) : TheodoliteException(message,e)
diff --git a/theodolite/src/main/kotlin/theodolite/execution/ExecutionModes.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecutionModes.kt
similarity index 74%
rename from theodolite/src/main/kotlin/theodolite/execution/ExecutionModes.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecutionModes.kt
index 370b87e062d942a512e059ee4041dca776376ddf..e8e4b642689c455b7be6c32d0bdedad58861238c 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/ExecutionModes.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecutionModes.kt
@@ -1,4 +1,4 @@
-package theodolite.execution
+package rocks.theodolite.kubernetes
 
 enum class ExecutionModes(val value: String) {
     OPERATOR("operator"),
diff --git a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExperimentRunnerImpl.kt
similarity index 52%
rename from theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExperimentRunnerImpl.kt
index 2e938be3a6e503a5e7e3f94c18a9454e173db5b0..e1ce46ea24fc97bb7b0421b8e3507c8e989d654a 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExperimentRunnerImpl.kt
@@ -1,57 +1,53 @@
-package theodolite.execution
+package rocks.theodolite.kubernetes
 
 import io.quarkus.runtime.annotations.RegisterForReflection
 import mu.KotlinLogging
-import theodolite.benchmark.Benchmark
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.evaluation.AnalysisExecutor
-import theodolite.execution.operator.EventCreator
-import theodolite.util.*
+import rocks.theodolite.core.ExperimentRunner
+import rocks.theodolite.core.Results
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark.Slo
+import rocks.theodolite.kubernetes.util.ConfigurationOverride
+import rocks.theodolite.kubernetes.operator.EventCreator
+import rocks.theodolite.kubernetes.slo.AnalysisExecutor
+import rocks.theodolite.kubernetes.patcher.PatcherDefinition
 import java.time.Duration
 import java.time.Instant
 
 private val logger = KotlinLogging.logger {}
 
 @RegisterForReflection
-class BenchmarkExecutorImpl(
-    benchmark: Benchmark,
+class ExperimentRunnerImpl(
     results: Results,
-    executionDuration: Duration,
-    configurationOverrides: List<ConfigurationOverride?>,
-    slos: List<BenchmarkExecution.Slo>,
-    repetitions: Int,
-    executionId: Int,
-    loadGenerationDelay: Long,
-    afterTeardownDelay: Long,
-    executionName: String
-) : BenchmarkExecutor(
-    benchmark,
-    results,
-    executionDuration,
-    configurationOverrides,
-    slos,
-    repetitions,
-    executionId,
-    loadGenerationDelay,
-    afterTeardownDelay,
-    executionName
+    private val benchmarkDeploymentBuilder: BenchmarkDeploymentBuilder,
+    private val executionDuration: Duration,
+    private val configurationOverrides: List<ConfigurationOverride?>,
+    private val slos: List<Slo>,
+    private val repetitions: Int,
+    private val executionId: Int,
+    private val loadGenerationDelay: Long,
+    private val afterTeardownDelay: Long,
+    private val executionName: String,
+    private val loadPatcherDefinitions: List<PatcherDefinition>,
+    private val resourcePatcherDefinitions: List<PatcherDefinition>,
+    private val waitForResourcesEnabled: Boolean
+) : ExperimentRunner(
+    results
 ) {
     private val eventCreator = EventCreator()
     private val mode = Configuration.EXECUTION_MODE
 
-    override fun runExperiment(load: LoadDimension, res: Resource): Boolean {
+    override fun runExperiment(load: Int, resource: Int): Boolean {
         var result = false
         val executionIntervals: MutableList<Pair<Instant, Instant>> = ArrayList()
 
         for (i in 1.rangeTo(repetitions)) {
             if (this.run.get()) {
                 logger.info { "Run repetition $i/$repetitions" }
-                executionIntervals.add(runSingleExperiment(load, res))
+                executionIntervals.add(runSingleExperiment(
+                        load, resource))
             } else {
                 break
             }
         }
-
         /**
          * Analyse the experiment, if [run] is true, otherwise the experiment was canceled by the user.
          */
@@ -60,41 +56,44 @@ class BenchmarkExecutorImpl(
                 AnalysisExecutor(slo = it, executionId = executionId)
                     .analyze(
                         load = load,
-                        res = res,
-                        executionIntervals = executionIntervals
+                        resource = resource,
+                        executionIntervals = executionIntervals,
+                        metric = this.results.metric
                     )
             }
 
             result = (false !in experimentResults)
-            this.results.setResult(Pair(load, res), result)
-        }
-
-        if(!this.run.get()) {
+            this.results.setResult(Pair(load, resource), result)
+        } else {
             throw ExecutionFailedException("The execution was interrupted")
         }
-
         return result
     }
 
-    private fun runSingleExperiment(load: LoadDimension, res: Resource): Pair<Instant, Instant> {
-        val benchmarkDeployment = benchmark.buildDeployment(
+    private fun runSingleExperiment(load: Int, resource: Int): Pair<Instant, Instant> {
+        val benchmarkDeployment = benchmarkDeploymentBuilder.buildDeployment(
             load,
-            res,
+            this.loadPatcherDefinitions,
+            resource,
+            this.resourcePatcherDefinitions,
             this.configurationOverrides,
             this.loadGenerationDelay,
-            this.afterTeardownDelay
+            this.afterTeardownDelay,
+            this.waitForResourcesEnabled
         )
-        val from = Instant.now()
+        val from: Instant
 
         try {
             benchmarkDeployment.setup()
+            from = Instant.now()
+
             this.waitAndLog()
             if (mode == ExecutionModes.OPERATOR.value) {
                 eventCreator.createEvent(
                     executionName = executionName,
                     type = "NORMAL",
                     reason = "Start experiment",
-                    message = "load: ${load.get()}, resources: ${res.get()}")
+                    message = "load: $load, resources: $resource")
             }
         } catch (e: Exception) {
             this.run.set(false)
@@ -104,7 +103,7 @@ class BenchmarkExecutorImpl(
                     executionName = executionName,
                     type = "WARNING",
                     reason = "Start experiment failed",
-                    message = "load: ${load.get()}, resources: ${res.get()}")
+                    message = "load: $load, resources: $resource")
             }
             throw ExecutionFailedException("Error during setup the experiment", e)
         }
@@ -130,4 +129,25 @@ class BenchmarkExecutorImpl(
         }
         return Pair(from, to)
     }
+
+    /**
+     * Wait while the benchmark is running and log the number of minutes executed every 1 minute.
+     */
+    fun waitAndLog() {
+        logger.info { "Execution of a new experiment started." }
+
+        var secondsRunning = 0L
+
+        while (run.get() && secondsRunning < executionDuration.toSeconds()) {
+            secondsRunning++
+            Thread.sleep(Duration.ofSeconds(1).toMillis())
+
+            if ((secondsRunning % 60) == 0L) {
+                logger.info { "Executed: ${secondsRunning / 60} minutes." }
+            }
+        }
+
+        logger.debug { "Executor shutdown gracefully." }
+
+    }
 }
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/FileSystemResourceSet.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/FileSystemResourceSet.kt
new file mode 100644
index 0000000000000000000000000000000000000000..44dacc044e2af477814be0399d23a5b14818bcee
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/FileSystemResourceSet.kt
@@ -0,0 +1,56 @@
+package rocks.theodolite.kubernetes
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.api.model.KubernetesResource
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient
+import io.quarkus.runtime.annotations.RegisterForReflection
+import java.io.BufferedReader
+import java.io.FileInputStream
+import java.io.FileNotFoundException
+import java.io.InputStreamReader
+import java.nio.charset.StandardCharsets
+import java.nio.file.Path
+import java.nio.file.Paths
+import java.util.stream.Collectors
+import kotlin.io.path.listDirectoryEntries
+
+
+@RegisterForReflection
+@JsonDeserialize
+class FileSystemResourceSet: ResourceSet, KubernetesResource {
+    lateinit var path: String
+    var files: List<String>? = null
+
+    override fun getResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, HasMetadata>> {
+        // if files is set ...
+        return files?.run {
+            return this
+                .map { Paths.get(path, it) }
+                .map { loadSingleResource(resource = it, client = client) }
+        } ?:
+        try {
+            Paths.get(path)
+                .listDirectoryEntries()
+                .filter { it.toString().endsWith(".yaml") || it.toString().endsWith(".yml") }
+                .map { loadSingleResource(resource = it, client = client) }
+        } catch (e: java.nio.file.NoSuchFileException) { // not to be confused with Kotlin exception
+            throw  DeploymentFailedException("Could not load files located in $path", e)
+        }
+    }
+
+    private fun loadSingleResource(resource: Path, client: NamespacedKubernetesClient): Pair<String, HasMetadata> {
+        return try {
+            val stream = FileInputStream(resource.toFile())
+            val text = BufferedReader(
+                InputStreamReader(stream, StandardCharsets.UTF_8)
+            ).lines().collect(Collectors.joining("\n"))
+            val k8sResource = client.resource(text).get()
+            Pair(resource.last().toString(), k8sResource)
+        } catch (e: FileNotFoundException){
+            throw DeploymentFailedException("File $resource not found.", e)
+        } catch (e: IllegalArgumentException) {
+            throw DeploymentFailedException("Could not load resource: $resource.", e)
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/K8sContextFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/K8sContextFactory.kt
similarity index 89%
rename from theodolite/src/main/kotlin/theodolite/k8s/K8sContextFactory.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/K8sContextFactory.kt
index 7eb209bfbab02bb94d34c985aa308173e509d4e4..880449d1952247bd7bf1784e083acc14ee59fea5 100644
--- a/theodolite/src/main/kotlin/theodolite/k8s/K8sContextFactory.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/K8sContextFactory.kt
@@ -1,4 +1,4 @@
-package theodolite.k8s
+package rocks.theodolite.kubernetes
 
 import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
 
@@ -7,6 +7,7 @@ import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
  *
  * @see CustomResourceDefinitionContext
  */
+@Deprecated("Use `CustomResourceDefinitionContext.Builder` instead.")
 class K8sContextFactory {
 
     /**
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/K8sManager.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/K8sManager.kt
similarity index 54%
rename from theodolite/src/main/kotlin/theodolite/k8s/K8sManager.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/K8sManager.kt
index 389d5eefad556df502c218862e2f253ef8ad2100..66bfb2572bfcb5cb53d579a8af1c94c2b39bb532 100644
--- a/theodolite/src/main/kotlin/theodolite/k8s/K8sManager.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/K8sManager.kt
@@ -1,8 +1,6 @@
-package theodolite.k8s
+package rocks.theodolite.kubernetes
 
-import io.fabric8.kubernetes.api.model.ConfigMap
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.api.model.Service
+import io.fabric8.kubernetes.api.model.HasMetadata
 import io.fabric8.kubernetes.api.model.apps.Deployment
 import io.fabric8.kubernetes.api.model.apps.StatefulSet
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
@@ -21,49 +19,31 @@ class K8sManager(private val client: NamespacedKubernetesClient) {
      * Deploys different k8s resources using the client.
      * @throws IllegalArgumentException if KubernetesResource not supported.
      */
-    fun deploy(resource: KubernetesResource) {
-        when (resource) {
-            is Deployment ->
-                this.client.apps().deployments().createOrReplace(resource)
-            is Service ->
-                this.client.services().createOrReplace(resource)
-            is ConfigMap ->
-                this.client.configMaps().createOrReplace(resource)
-            is StatefulSet ->
-                this.client.apps().statefulSets().createOrReplace(resource)
-            is CustomResourceWrapper -> resource.deploy(client)
-            else -> throw IllegalArgumentException("Unknown Kubernetes resource.")
-        }
+    fun deploy(resource: HasMetadata) {
+        client.resource(resource).createOrReplace()
     }
 
     /**
      * Removes different k8s resources using the client.
      * @throws IllegalArgumentException if KubernetesResource not supported.
      */
-    fun remove(resource: KubernetesResource) {
+    fun remove(resource: HasMetadata) {
+        client.resource(resource).delete()
         when (resource) {
             is Deployment -> {
-                this.client.apps().deployments().delete(resource)
                 ResourceByLabelHandler(client = client)
                     .blockUntilPodsDeleted(
                         matchLabels = resource.spec.selector.matchLabels
                     )
                 logger.info { "Deployment '${resource.metadata.name}' deleted." }
             }
-            is Service ->
-                this.client.services().delete(resource)
-            is ConfigMap ->
-                this.client.configMaps().delete(resource)
             is StatefulSet -> {
-                this.client.apps().statefulSets().delete(resource)
                 ResourceByLabelHandler(client = client)
                     .blockUntilPodsDeleted(
                         matchLabels = resource.spec.selector.matchLabels
                     )
                 logger.info { "StatefulSet '$resource.metadata.name' deleted." }
             }
-            is CustomResourceWrapper -> resource.delete(client)
-            else -> throw IllegalArgumentException("Unknown Kubernetes resource.")
         }
     }
 }
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkDeployment.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/KubernetesBenchmarkDeployment.kt
similarity index 82%
rename from theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkDeployment.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/KubernetesBenchmarkDeployment.kt
index 3331444a17b4c2a1aa4411c1e27b3d1e087f8841..be567ccd8ec969a4964886e20f141fa4fad17b88 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkDeployment.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/KubernetesBenchmarkDeployment.kt
@@ -1,14 +1,14 @@
-package theodolite.benchmark
+package rocks.theodolite.kubernetes
 
+import io.fabric8.kubernetes.api.model.HasMetadata
 import io.fabric8.kubernetes.api.model.KubernetesResource
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.quarkus.runtime.annotations.RegisterForReflection
 import mu.KotlinLogging
 import org.apache.kafka.clients.admin.NewTopic
-import theodolite.k8s.K8sManager
-import theodolite.k8s.ResourceByLabelHandler
-import theodolite.k8s.TopicManager
-import theodolite.util.KafkaConfig
+import rocks.theodolite.kubernetes.kafka.TopicManager
+import rocks.theodolite.kubernetes.model.crd.KafkaConfig
+import theodolite.benchmark.RolloutManager
 import java.time.Duration
 
 private val logger = KotlinLogging.logger {}
@@ -27,8 +27,9 @@ class KubernetesBenchmarkDeployment(
     private val sutAfterActions: List<Action>,
     private val loadGenBeforeActions: List<Action>,
     private val loadGenAfterActions: List<Action>,
-    val appResources: List<KubernetesResource>,
-    val loadGenResources: List<KubernetesResource>,
+    private val rolloutMode: Boolean,
+    val appResources: List<HasMetadata>,
+    val loadGenResources: List<HasMetadata>,
     private val loadGenerationDelay: Long,
     private val afterTeardownDelay: Long,
     private val kafkaConfig: Map<String, Any>,
@@ -38,7 +39,9 @@ class KubernetesBenchmarkDeployment(
     private val kafkaController = TopicManager(this.kafkaConfig)
     private val kubernetesManager = K8sManager(client)
     private val LAG_EXPORTER_POD_LABEL_NAME = "app.kubernetes.io/name"
-    private val LAG_EXPORTER_POD_LABEL_VALUE = "kafka-lag-exporter"
+    private val LAG_EXPORTER_POD_LABEL_VALUE = "kafka-exporter"
+
+
 
     /**
      * Setup a [KubernetesBenchmark] using the [TopicManager] and the [K8sManager]:
@@ -46,19 +49,20 @@ class KubernetesBenchmarkDeployment(
      *  - Deploy the needed resources.
      */
     override fun setup() {
+        val rolloutManager = RolloutManager(rolloutMode, client)
         if (this.topics.isNotEmpty()) {
             val kafkaTopics = this.topics
                 .filter { !it.removeOnly }
                 .map { NewTopic(it.name, it.numPartitions, it.replicationFactor) }
             kafkaController.createTopics(kafkaTopics)
         }
+
         sutBeforeActions.forEach { it.exec(client = client) }
-        appResources.forEach { kubernetesManager.deploy(it) }
+        rolloutManager.rollout(appResources)
         logger.info { "Wait ${this.loadGenerationDelay} seconds before starting the load generator." }
         Thread.sleep(Duration.ofSeconds(this.loadGenerationDelay).toMillis())
         loadGenBeforeActions.forEach { it.exec(client = client) }
-        loadGenResources.forEach { kubernetesManager.deploy(it) }
-
+        rolloutManager.rollout(loadGenResources)
     }
 
     /**
@@ -79,7 +83,7 @@ class KubernetesBenchmarkDeployment(
             labelName = LAG_EXPORTER_POD_LABEL_NAME,
             labelValue = LAG_EXPORTER_POD_LABEL_VALUE
         )
-        logger.info { "Teardown complete. Wait $afterTeardownDelay ms to let everything come down." }
+        logger.info { "Teardown complete. Wait $afterTeardownDelay seconds to let everything cool down." }
         Thread.sleep(Duration.ofSeconds(afterTeardownDelay).toMillis())
     }
 }
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/KubernetesBenchmarkDeploymentBuilder.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/KubernetesBenchmarkDeploymentBuilder.kt
new file mode 100644
index 0000000000000000000000000000000000000000..67fe92afb8aa4c9edda2474fc6307c16c21a41f6
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/KubernetesBenchmarkDeploymentBuilder.kt
@@ -0,0 +1,92 @@
+package rocks.theodolite.kubernetes
+
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient
+import mu.KotlinLogging
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark
+import rocks.theodolite.kubernetes.patcher.PatchHandler
+import rocks.theodolite.kubernetes.util.ConfigurationOverride
+import rocks.theodolite.kubernetes.patcher.PatcherDefinition
+
+private val logger = KotlinLogging.logger {}
+
+class KubernetesBenchmarkDeploymentBuilder (val kubernetesBenchmark: KubernetesBenchmark,
+                                            private var client: NamespacedKubernetesClient)
+    : BenchmarkDeploymentBuilder {
+
+
+    /**
+     * Builds a deployment.
+     * First loads all required resources and then patches them to the concrete load and resources for the experiment for the demand metric
+     * or loads all loads and then patches them to the concrete load and resources for the experiment.
+     * Afterwards patches additional configurations(cluster depending) into the resources (or loads).
+     * @param load concrete load that will be benchmarked in this experiment (demand metric), or scaled (capacity metric).
+     * @param resource concrete resource that will be scaled for this experiment (demand metric), or benchmarked (capacity metric).
+     * @param configurationOverrides
+     * @return a [BenchmarkDeployment]
+     */
+    override fun buildDeployment(
+            load: Int,
+            loadPatcherDefinitions: List<PatcherDefinition>,
+            resource: Int,
+            resourcePatcherDefinitions: List<PatcherDefinition>,
+            configurationOverrides: List<ConfigurationOverride?>,
+            loadGenerationDelay: Long,
+            afterTeardownDelay: Long,
+            waitForResourcesEnabled: Boolean
+    ): BenchmarkDeployment {
+        logger.info { "Using ${this.client.namespace} as namespace." }
+
+        val appResources = loadKubernetesResources(kubernetesBenchmark.sut.resources, this.client).toResourceMap()
+        val loadGenResources = loadKubernetesResources(kubernetesBenchmark.loadGenerator.resources, this.client).toResourceMap()
+
+        // patch the load dimension the resources
+        loadPatcherDefinitions.forEach { patcherDefinition ->
+            loadGenResources[patcherDefinition.resource] =
+                PatchHandler.patchResource(loadGenResources, patcherDefinition, load.toString())
+        }
+        resourcePatcherDefinitions.forEach { patcherDefinition ->
+            appResources[patcherDefinition.resource] =
+                PatchHandler.patchResource(appResources, patcherDefinition, resource.toString())
+        }
+
+        // Patch the given overrides
+        configurationOverrides.forEach { override ->
+            override?.let {
+                if (appResources.keys.contains(it.patcher.resource)) {
+                    appResources[it.patcher.resource] =
+                        PatchHandler.patchResource(appResources, override.patcher, override.value)
+                } else {
+                    loadGenResources[it.patcher.resource] =
+                        PatchHandler.patchResource(loadGenResources, override.patcher, override.value)
+                }
+            }
+        }
+
+        val kafkaConfig = kubernetesBenchmark.kafkaConfig
+
+        return KubernetesBenchmarkDeployment(
+                sutBeforeActions = kubernetesBenchmark.sut.beforeActions,
+                sutAfterActions = kubernetesBenchmark.sut.afterActions,
+                loadGenBeforeActions = kubernetesBenchmark.loadGenerator.beforeActions,
+                loadGenAfterActions = kubernetesBenchmark.loadGenerator.afterActions,
+                appResources = appResources.toList().flatMap { it.second },
+                loadGenResources = loadGenResources.toList().flatMap { it.second },
+                loadGenerationDelay = loadGenerationDelay,
+                afterTeardownDelay = afterTeardownDelay,
+                kafkaConfig = if (kafkaConfig != null) mapOf("bootstrap.servers" to kafkaConfig.bootstrapServer) else mapOf(),
+                topics = kafkaConfig?.topics ?: listOf(),
+                client = this.client,
+                rolloutMode = waitForResourcesEnabled
+        )
+    }
+
+}
+
+private fun Collection<Pair<String, HasMetadata>>.toResourceMap(): MutableMap<String, List<HasMetadata>> {
+    return this.toMap()
+        .toMutableMap()
+        .map { Pair(it.key, listOf(it.value)) }
+        .toMap()
+        .toMutableMap()
+}
diff --git a/theodolite/src/main/kotlin/theodolite/execution/Main.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Main.kt
similarity index 57%
rename from theodolite/src/main/kotlin/theodolite/execution/Main.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Main.kt
index 17b3d4e7b86f9e430abfb6093e79aa7865cd5923..cbd7c3106b39c4571d559d4071cd4ac16e180bc8 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/Main.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Main.kt
@@ -1,9 +1,11 @@
-package theodolite.execution
+package rocks.theodolite.kubernetes
 
+import io.fabric8.kubernetes.client.DefaultKubernetesClient
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.quarkus.runtime.annotations.QuarkusMain
 import mu.KotlinLogging
-import theodolite.execution.operator.TheodoliteOperator
-import theodolite.util.Configuration
+import rocks.theodolite.kubernetes.operator.TheodoliteOperator
+import rocks.theodolite.kubernetes.standalone.TheodoliteStandalone
 import kotlin.system.exitProcess
 
 private val logger = KotlinLogging.logger {}
@@ -17,9 +19,12 @@ object Main {
         val mode = Configuration.EXECUTION_MODE
         logger.info { "Start Theodolite with mode $mode" }
 
+        val namespace = Configuration.NAMESPACE
+        val client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(namespace)
+
         when (mode.lowercase()) {
-            ExecutionModes.STANDALONE.value -> TheodoliteStandalone().start()
-            ExecutionModes.OPERATOR.value -> TheodoliteOperator().start()
+            ExecutionModes.STANDALONE.value -> TheodoliteStandalone(client).start()
+            ExecutionModes.OPERATOR.value -> TheodoliteOperator(client).start()
             else -> {
                 logger.error { "MODE $mode not found" }
                 exitProcess(1)
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/ResourceByLabelHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceByLabelHandler.kt
similarity index 99%
rename from theodolite/src/main/kotlin/theodolite/k8s/ResourceByLabelHandler.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceByLabelHandler.kt
index 518b8eae211dd064e3c12b0713382bf3b12bb1ba..c65235f5fef304a7644399573380b4147704cb6c 100644
--- a/theodolite/src/main/kotlin/theodolite/k8s/ResourceByLabelHandler.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceByLabelHandler.kt
@@ -1,4 +1,4 @@
-package theodolite.k8s
+package rocks.theodolite.kubernetes
 
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSet.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceSet.kt
similarity index 92%
rename from theodolite/src/main/kotlin/theodolite/benchmark/ResourceSet.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceSet.kt
index 19fc85845ae99c7a5e4f7369db4b6cd383c3131b..9910d0ac89a9b423047f4f20f07a8015cbb24f9a 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSet.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceSet.kt
@@ -1,4 +1,4 @@
-package theodolite.benchmark
+package rocks.theodolite.kubernetes
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.fabric8.kubernetes.api.model.KubernetesResource
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceSets.kt
similarity index 50%
rename from theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceSets.kt
index b6364949727d4ea134e348ce8b79e22334753c1c..f57835a1e2459b0ce8989a4f1c745cc272e5f1e9 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceSets.kt
@@ -1,16 +1,23 @@
-package theodolite.benchmark
+package rocks.theodolite.kubernetes
 
 import com.fasterxml.jackson.annotation.JsonInclude
 import com.fasterxml.jackson.annotation.JsonProperty
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+import io.fabric8.kubernetes.api.model.HasMetadata
 import io.fabric8.kubernetes.api.model.KubernetesResource
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.quarkus.runtime.annotations.RegisterForReflection
-import theodolite.util.DeploymentFailedException
+
+/**
+ * Loads [KubernetesResource]s.
+ */
+fun loadKubernetesResources(resourceSet: List<ResourceSets>, client: NamespacedKubernetesClient): Collection<Pair<String, HasMetadata>> {
+    return resourceSet.flatMap { it.loadResourceSet(client) }
+}
 
 @JsonDeserialize
 @RegisterForReflection
-class ResourceSets: KubernetesResource {
+class ResourceSets : KubernetesResource {
     @JsonProperty("configMap")
     @JsonInclude(JsonInclude.Include.NON_NULL)
     var configMap: ConfigMapResourceSet? = null
@@ -19,13 +26,14 @@ class ResourceSets: KubernetesResource {
     @JsonInclude(JsonInclude.Include.NON_NULL)
     var fileSystem: FileSystemResourceSet? = null
 
-    fun loadResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, KubernetesResource>> {
-        return if (::configMap != null) {
-            configMap?.getResourceSet(client= client) !!
-            } else if (::fileSystem != null) {
-            fileSystem?.getResourceSet(client= client ) !!
-            } else {
-                throw  DeploymentFailedException("could not load resourceSet.")
-            }
+
+    fun loadResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, HasMetadata>> {
+        return if (this.configMap != null) {
+            configMap?.getResourceSet(client = client)!!
+        } else if (this.fileSystem != null) {
+            fileSystem?.getResourceSet(client = client)!!
+        } else {
+            throw DeploymentFailedException("Could not load resourceSet.")
+        }
     }
 }
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/RolloutManager.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/RolloutManager.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f760bb407ec2a6c4ab2ee08d3521ad72d12dd25d
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/RolloutManager.kt
@@ -0,0 +1,39 @@
+package theodolite.benchmark
+
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.api.model.apps.DaemonSet
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.fabric8.kubernetes.api.model.apps.ReplicaSet
+import io.fabric8.kubernetes.api.model.apps.StatefulSet
+import io.fabric8.kubernetes.api.model.batch.v1.Job
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient
+import rocks.theodolite.kubernetes.K8sManager
+
+private var SLEEP_TIME_MS = 500L
+class RolloutManager(private val blockUntilResourcesReady: Boolean, private val client: NamespacedKubernetesClient) {
+
+    fun rollout(resources: List<HasMetadata>) {
+        resources
+            .forEach { K8sManager(client).deploy(it) }
+
+        if (blockUntilResourcesReady) {
+            resources
+                .forEach {
+                    when (it) {
+                        is Deployment -> waitFor { client.apps().deployments().withName(it.metadata.name).isReady }
+                        is StatefulSet -> waitFor { client.apps().statefulSets().withName(it.metadata.name).isReady }
+                        is DaemonSet -> waitFor { client.apps().daemonSets().withName(it.metadata.name).isReady }
+                        is ReplicaSet -> waitFor { client.apps().replicaSets().withName(it.metadata.name).isReady }
+                        is Job -> waitFor { client.batch().v1().cronjobs().withName(it.metadata.name).isReady }
+                    }
+                }
+        }
+    }
+
+    private fun waitFor(isResourceReady: () -> Boolean) {
+        while (!isResourceReady()) {
+            Thread.sleep(SLEEP_TIME_MS)
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Shutdown.kt
similarity index 58%
rename from theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Shutdown.kt
index 29ac39c122f68636e08c6c5ecd5a6c01751edafb..e970c84d345031b79f8afeedf56591e071bb154f 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Shutdown.kt
@@ -1,10 +1,9 @@
-package theodolite.execution
+package rocks.theodolite.kubernetes
 
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import mu.KotlinLogging
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.benchmark.KubernetesBenchmark
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
+import rocks.theodolite.kubernetes.model.BenchmarkExecution
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark
 
 private val logger = KotlinLogging.logger {}
 
@@ -14,7 +13,9 @@ private val logger = KotlinLogging.logger {}
  * @property benchmarkExecution
  * @property benchmark
  */
-class Shutdown(private val benchmarkExecution: BenchmarkExecution, private val benchmark: KubernetesBenchmark) {
+class Shutdown(private val benchmarkExecution: BenchmarkExecution,
+               private val benchmark: KubernetesBenchmark,
+               private val client: NamespacedKubernetesClient) {
 
     /**
      * Run
@@ -22,15 +23,19 @@ class Shutdown(private val benchmarkExecution: BenchmarkExecution, private val b
      */
     fun run() {
         // Build Configuration to teardown
+        val benchmarkDeploymentBuilder = KubernetesBenchmarkDeploymentBuilder(benchmark, this.client)
         try {
             logger.info { "Received shutdown signal -> Shutting down" }
             val deployment =
-                benchmark.buildDeployment(
-                    load = LoadDimension(0, emptyList()),
-                    res = Resource(0, emptyList()),
+                    benchmarkDeploymentBuilder.buildDeployment(
+                    load = 0,
+                    loadPatcherDefinitions = emptyList(),
+                    resource = 0,
+                    resourcePatcherDefinitions = emptyList(),
                     configurationOverrides = benchmarkExecution.configOverrides,
                     loadGenerationDelay = 0L,
-                    afterTeardownDelay = 5L
+                    afterTeardownDelay = 5L,
+                    waitForResourcesEnabled = benchmark.waitForResourcesEnabled
                 )
             deployment.teardown()
             logger.info { "Finished teardown of all benchmark resources." }
diff --git a/theodolite/src/main/kotlin/theodolite/util/TheodoliteException.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/TheodoliteException.kt
similarity index 72%
rename from theodolite/src/main/kotlin/theodolite/util/TheodoliteException.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/TheodoliteException.kt
index fc7453bae6aaa4c5c526eee72c006562ea887eb5..6a4374c3e3c9435c498c8e15e8c5efaa01fd89cd 100644
--- a/theodolite/src/main/kotlin/theodolite/util/TheodoliteException.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/TheodoliteException.kt
@@ -1,3 +1,3 @@
-package theodolite.util
+package rocks.theodolite.kubernetes
 
 open class TheodoliteException (message: String, e: Exception? = null) : Exception(message,e)
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/TheodoliteExecutor.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/TheodoliteExecutor.kt
new file mode 100644
index 0000000000000000000000000000000000000000..69615522ba9bbd5ef0944528eacbf1dce318caf9
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/TheodoliteExecutor.kt
@@ -0,0 +1,169 @@
+package rocks.theodolite.kubernetes
+
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient
+import mu.KotlinLogging
+import rocks.theodolite.core.ExecutionRunner
+import rocks.theodolite.core.ExperimentRunner
+import rocks.theodolite.kubernetes.model.BenchmarkExecution
+import rocks.theodolite.kubernetes.patcher.PatcherDefinitionFactory
+import rocks.theodolite.core.strategies.Metric
+import rocks.theodolite.core.strategies.StrategyFactory
+import rocks.theodolite.core.Config
+import rocks.theodolite.core.IOHandler
+import rocks.theodolite.core.Results
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark
+import rocks.theodolite.kubernetes.slo.SloFactory
+import java.io.File
+import java.time.Duration
+
+
+private val logger = KotlinLogging.logger {}
+
+/**
+ * The Theodolite executor runs all the experiments defined with the given execution and benchmark configuration.
+ *
+ * @property benchmarkExecution Configuration of a execution
+ * @property benchmark Configuration of a benchmark
+ * @constructor Create empty Theodolite executor
+ */
+class TheodoliteExecutor(
+        private val benchmarkExecution: BenchmarkExecution,
+        private val benchmark: KubernetesBenchmark,
+        private val client: NamespacedKubernetesClient
+) {
+    /**
+     * An executor object, configured with the specified benchmark, evaluation method, experiment duration
+     * and overrides which are given in the execution.
+     */
+    lateinit var experimentRunner: ExperimentRunner
+
+    /**
+     * Creates all required components to start Theodolite.
+     *
+     * @return a [Config], that contains a list of LoadDimension s,
+     *          a list of Resource s , and the [restrictionSearch].
+     * The [SearchStrategy] is configured and able to find the minimum required resource for the given load.
+     */
+    private fun buildConfig(): Config {
+        val results = Results(Metric.from(benchmarkExecution.execution.metric))
+        val strategyFactory = StrategyFactory()
+
+        val executionDuration = Duration.ofSeconds(benchmarkExecution.execution.duration)
+
+        val resourcePatcherDefinition =
+            PatcherDefinitionFactory().createPatcherDefinition(
+                benchmarkExecution.resources.resourceType,
+                this.benchmark.resourceTypes
+            )
+
+        val loadDimensionPatcherDefinition =
+            PatcherDefinitionFactory().createPatcherDefinition(
+                benchmarkExecution.loads.loadType,
+                this.benchmark.loadTypes
+            )
+
+        val slos = SloFactory().createSlos(this.benchmarkExecution, this.benchmark)
+
+        experimentRunner =
+            ExperimentRunnerImpl(
+                benchmarkDeploymentBuilder = KubernetesBenchmarkDeploymentBuilder(this.benchmark,this.client),
+                results = results,
+                executionDuration = executionDuration,
+                configurationOverrides = benchmarkExecution.configOverrides,
+                slos = slos,
+                repetitions = benchmarkExecution.execution.repetitions,
+                executionId = benchmarkExecution.executionId,
+                loadGenerationDelay = benchmarkExecution.execution.loadGenerationDelay,
+                afterTeardownDelay = benchmarkExecution.execution.afterTeardownDelay,
+                executionName = benchmarkExecution.name,
+                loadPatcherDefinitions = loadDimensionPatcherDefinition,
+                resourcePatcherDefinitions = resourcePatcherDefinition,
+                waitForResourcesEnabled = this.benchmark.waitForResourcesEnabled
+            )
+
+        if (benchmarkExecution.loads.loadValues != benchmarkExecution.loads.loadValues.sorted()) {
+            benchmarkExecution.loads.loadValues = benchmarkExecution.loads.loadValues.sorted()
+            logger.info {
+                "Load values are not sorted correctly, Theodolite sorts them in ascending order." +
+                        "New order is: ${benchmarkExecution.loads.loadValues}"
+            }
+        }
+
+        if (benchmarkExecution.resources.resourceValues != benchmarkExecution.resources.resourceValues.sorted()) {
+            benchmarkExecution.resources.resourceValues = benchmarkExecution.resources.resourceValues.sorted()
+            logger.info {
+                "Load values are not sorted correctly, Theodolite sorts them in ascending order." +
+                        "New order is: ${benchmarkExecution.resources.resourceValues}"
+            }
+        }
+
+        return Config(
+            loads = benchmarkExecution.loads.loadValues,
+            resources = benchmarkExecution.resources.resourceValues,
+            searchStrategy = strategyFactory.createSearchStrategy(experimentRunner, benchmarkExecution.execution.strategy.name,
+                    benchmarkExecution.execution.strategy.searchStrategy, benchmarkExecution.execution.strategy.restrictions,
+                    benchmarkExecution.execution.strategy.guessStrategy, results),
+            metric = Metric.from(benchmarkExecution.execution.metric)
+        )
+    }
+
+    /**
+     * Sets up the Infrastructure, increments the executionId, calls the [ExecutionRunner] that runs
+     * all experiments which are specified in the corresponding execution and benchmark objects.
+     */
+    fun setupAndRunExecution() {
+        setupInfrastructure()
+
+        val ioHandler = IOHandler()
+        val resultsFolder = ioHandler.getResultFolderURL()
+        this.benchmarkExecution.executionId = getAndIncrementExecutionID(resultsFolder + "expID.txt")
+        ioHandler.writeToJSONFile(this.benchmarkExecution, "${resultsFolder}exp${this.benchmarkExecution.executionId}-execution-configuration")
+        ioHandler.writeToJSONFile(
+                benchmark,
+            "${resultsFolder}exp${this.benchmarkExecution.executionId}-benchmark-configuration"
+        )
+
+        val config = buildConfig()
+
+        val executionRunner = ExecutionRunner(config.searchStrategy, config.resources, config.loads,config.metric,
+                                              this.benchmarkExecution.executionId)
+
+        executionRunner.run()
+
+        teardownInfrastructure()
+    }
+
+    private fun setupInfrastructure() {
+        benchmark.infrastructure.beforeActions.forEach { it.exec(client = client) }
+        val kubernetesManager = K8sManager(this.client)
+        loadKubernetesResources(benchmark.infrastructure.resources, this.client)
+                .map { it.second }
+                .forEach { kubernetesManager.deploy(it) }
+    }
+
+    private fun teardownInfrastructure() {
+        val kubernetesManager = K8sManager(this.client)
+        loadKubernetesResources(benchmark.infrastructure.resources, this.client)
+                .map { it.second }
+                .forEach { kubernetesManager.remove(it) }
+        benchmark.infrastructure.afterActions.forEach { it.exec(client = client) }
+    }
+
+    private fun getAndIncrementExecutionID(fileURL: String): Int {
+        val ioHandler = IOHandler()
+        var executionID = 0
+        if (File(fileURL).exists()) {
+            executionID = ioHandler.readFileAsString(fileURL).toInt() + 1
+        }
+        ioHandler.writeStringToTextFile(fileURL, (executionID).toString())
+        return executionID
+    }
+
+    private fun calculateMetric(xValues: List<Int>, results: Results): List<List<String>> {
+        return xValues.map { listOf(it.toString(), results.getOptYDimensionValue(it).toString()) }
+    }
+
+    fun getExecution(): BenchmarkExecution {
+        return this.benchmarkExecution
+    }
+}
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/kafka/TopicManager.kt
similarity index 98%
rename from theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/kafka/TopicManager.kt
index ed1e06571d20c53fc82439833c8a31800a48b602..e9a0cb4b3c0863baf54a8dda58b96c81a80af60d 100644
--- a/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/kafka/TopicManager.kt
@@ -1,4 +1,4 @@
-package theodolite.k8s
+package rocks.theodolite.kubernetes.kafka
 
 import mu.KotlinLogging
 import org.apache.kafka.clients.admin.AdminClient
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/BenchmarkExecution.kt
similarity index 58%
rename from theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/BenchmarkExecution.kt
index f2dda487d390c5f771e4f47c0f9c7ebf2cf971e7..167423ec911cd740b0ee0246e8512dde8402f1e9 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/BenchmarkExecution.kt
@@ -1,9 +1,9 @@
-package theodolite.benchmark
+package rocks.theodolite.kubernetes.model
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.fabric8.kubernetes.api.model.KubernetesResource
 import io.quarkus.runtime.annotations.RegisterForReflection
-import theodolite.util.ConfigurationOverride
+import rocks.theodolite.kubernetes.util.ConfigurationOverride
 import kotlin.properties.Delegates
 
 /**
@@ -12,9 +12,9 @@ import kotlin.properties.Delegates
  * A BenchmarkExecution consists of:
  *  - A [name].
  *  - The [benchmark] that should be executed.
- *  - The [load] that should be checked in the benchmark.
+ *  - The [loads]s that should be checked in the benchmark.
  *  - The [resources] that should be checked in the benchmark.
- *  - A list of [slos] that are used for the evaluation of the experiments.
+ *  - The [slos] further restrict the Benchmark SLOs for the evaluation of the experiments.
  *  - An [execution] that encapsulates: the strategy, the duration, and the restrictions
  *  for the execution of the benchmark.
  *  - [configOverrides] additional configurations.
@@ -28,48 +28,55 @@ class BenchmarkExecution : KubernetesResource {
     var executionId: Int = 0
     lateinit var name: String
     lateinit var benchmark: String
-    lateinit var load: LoadDefinition
+    lateinit var loads: LoadDefinition
     lateinit var resources: ResourceDefinition
-    lateinit var slos: List<Slo>
+    lateinit var slos: List<SloConfiguration>
     lateinit var execution: Execution
     lateinit var configOverrides: MutableList<ConfigurationOverride?>
 
     /**
-     * This execution encapsulates the [strategy], the [duration], the [repetitions], and the [restrictions]
+     * This execution encapsulates the [strategy], the [duration], and the [repetitions],
      *  which are used for the concrete benchmark experiments.
      */
     @JsonDeserialize
     @RegisterForReflection
     class Execution : KubernetesResource {
-        lateinit var strategy: String
+        var metric = "demand"
+        lateinit var strategy: Strategy
         var duration by Delegates.notNull<Long>()
         var repetitions by Delegates.notNull<Int>()
-        lateinit var restrictions: List<String>
         var loadGenerationDelay = 0L
         var afterTeardownDelay = 5L
     }
 
     /**
-     * Measurable metric.
-     * [sloType] determines the type of the metric.
-     * It is evaluated using the [theodolite.evaluation.ExternalSloChecker] by data measured by Prometheus.
-     * The evaluation checks if a [threshold] is reached or not.
-     * [offset] determines the shift in hours by which the start and end timestamps should be shifted.
-     * The [warmup] determines after which time the metric should be evaluated to avoid starting interferences.
-     * The [warmup] time unit depends on the Slo: for the lag trend it is in seconds.
+     * This Strategy encapsulates the [restrictions], [guessStrategy] and [searchStrategy],
+     * which are used for restricting the resources, the guess Strategy for the
+     * [theodolite.strategies.searchstrategy.InitialGuessSearchStrategy] and the name of the actual
+     * [theodolite.strategies.searchstrategy.SearchStrategy] which is used.
      */
     @JsonDeserialize
     @RegisterForReflection
-    class Slo : KubernetesResource {
-        lateinit var sloType: String
-        lateinit var prometheusUrl: String
-        var offset by Delegates.notNull<Int>()
-        lateinit var properties: MutableMap<String, String>
+    class Strategy : KubernetesResource {
+        lateinit var name: String
+        var restrictions = emptyList<String>()
+        var guessStrategy = ""
+        var searchStrategy = ""
     }
 
     /**
-     * Represents a Load that should be created and checked.
-     * It can be set to [loadValues].
+     * Further SLO configurations for the SLOs specified in the Benchmark.
+     */
+    @JsonDeserialize
+    @RegisterForReflection
+    class SloConfiguration : KubernetesResource {
+        lateinit var name: String
+        var properties: MutableMap<String, String>? = null
+    }
+
+    /**
+     * Represents the Loads that should be created and checked if the demand metric is in use or
+     * represents a Load that can be scaled to [loadValues] if the capacity metric is in use.
      */
     @JsonDeserialize
     @RegisterForReflection
@@ -79,7 +86,8 @@ class BenchmarkExecution : KubernetesResource {
     }
 
     /**
-     * Represents a resource that can be scaled to [resourceValues].
+     * Represents a resource that can be scaled to [resourceValues] if the demand metric is in use or
+     * represents the Resources that should be created and checked if the capacity metric is in use.
      */
     @JsonDeserialize
     @RegisterForReflection
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/KubernetesBenchmark.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/KubernetesBenchmark.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9c1412af7e6a86fbb248e8be7d1a97259a59c8d0
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/KubernetesBenchmark.kt
@@ -0,0 +1,77 @@
+package rocks.theodolite.kubernetes.model
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+import io.fabric8.kubernetes.api.model.KubernetesResource
+import io.quarkus.runtime.annotations.RegisterForReflection
+import rocks.theodolite.kubernetes.Action
+import rocks.theodolite.kubernetes.ResourceSets
+import rocks.theodolite.kubernetes.model.crd.KafkaConfig
+import rocks.theodolite.kubernetes.patcher.PatcherDefinition
+import kotlin.properties.Delegates
+
+/**
+ * Represents a benchmark in Kubernetes. An example for this is the BenchmarkType.yaml
+ * Contains a of:
+ * - [name] of the benchmark,
+ * - [appResource] list of the resources that have to be deployed for the benchmark,
+ * - [loadGenResource] resource that generates the load,
+ * - [resourceTypes] types of scaling resources,
+ * - [loadTypes] types of loads that can be scaled for the benchmark,
+ * - [kafkaConfig] for the [theodolite.k8s.TopicManager],
+ * - [namespace] for the client,
+ * - [path] under which the resource yamls can be found.
+ *
+ *  This class is used for the parsing(in the [theodolite.execution.TheodoliteStandalone]) and
+ *  for the deserializing in the [theodolite.execution.operator.TheodoliteOperator].
+ * @constructor construct an empty Benchmark.
+ */
+@JsonDeserialize
+@RegisterForReflection
+class KubernetesBenchmark : KubernetesResource {
+    lateinit var name: String
+    var waitForResourcesEnabled = false
+    lateinit var resourceTypes: List<TypeName>
+    lateinit var loadTypes: List<TypeName>
+    lateinit var slos: MutableList<Slo>
+    var kafkaConfig: KafkaConfig? = null
+    lateinit var infrastructure: Resources
+    lateinit var sut: Resources
+    lateinit var loadGenerator: Resources
+
+    /**
+     * The TypeName encapsulates a list of [PatcherDefinition] along with a typeName that specifies for what the [PatcherDefinition] should be used.
+     */
+    @RegisterForReflection
+    @JsonDeserialize
+    class TypeName {
+        lateinit var typeName: String
+        lateinit var patchers: List<PatcherDefinition>
+    }
+
+    /**
+     * Measurable metric.
+     * [sloType] determines the type of the metric.
+     * It is evaluated using the [theodolite.evaluation.ExternalSloChecker] by data measured by Prometheus.
+     * The evaluation checks if a [threshold] is reached or not.
+     * [offset] determines the shift in hours by which the start and end timestamps should be shifted.
+     * The [warmup] determines after which time the metric should be evaluated to avoid starting interferences.
+     * The [warmup] time unit depends on the Slo: for the lag trend it is in seconds.
+     */
+    @JsonDeserialize
+    @RegisterForReflection
+    class Slo : KubernetesResource {
+        lateinit var name: String
+        lateinit var sloType: String
+        lateinit var prometheusUrl: String
+        var offset by Delegates.notNull<Int>()
+        lateinit var properties: MutableMap<String, String>
+    }
+
+    @JsonDeserialize
+    @RegisterForReflection
+    class Resources {
+        lateinit var resources: List<ResourceSets>
+        lateinit var beforeActions: List<Action>
+        lateinit var afterActions: List<Action>
+    }
+}
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkCRD.kt
similarity index 86%
rename from theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkCRD.kt
index 0ec6decbdea5e192721a4f9b6d0d85ea65665a5a..f480177e4482ab48df01593fdc10ea459a87ca43 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkCRD.kt
@@ -1,4 +1,4 @@
-package theodolite.model.crd
+package rocks.theodolite.kubernetes.model.crd
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.fabric8.kubernetes.api.model.Namespaced
@@ -6,7 +6,7 @@ import io.fabric8.kubernetes.client.CustomResource
 import io.fabric8.kubernetes.model.annotation.Group
 import io.fabric8.kubernetes.model.annotation.Kind
 import io.fabric8.kubernetes.model.annotation.Version
-import theodolite.benchmark.KubernetesBenchmark
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark
 
 @JsonDeserialize
 @Version("v1")
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkExecutionList.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkExecutionList.kt
similarity index 72%
rename from theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkExecutionList.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkExecutionList.kt
index 2b2dcc07f9c37f1712109e3d092f2db0c139e1c8..768cd7c4f7edf2f254905539214177638ad5283c 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkExecutionList.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkExecutionList.kt
@@ -1,4 +1,4 @@
-package theodolite.model.crd
+package rocks.theodolite.kubernetes.model.crd
 
 import io.fabric8.kubernetes.client.CustomResourceList
 
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkState.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkState.kt
similarity index 77%
rename from theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkState.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkState.kt
index dc2c6f9ba971367c0bb142a54745629eb29c07d5..928a411725f5eaf71839f4b7109b69ff40eb8807 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkState.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkState.kt
@@ -1,4 +1,4 @@
-package theodolite.model.crd
+package rocks.theodolite.kubernetes.model.crd
 
 import com.fasterxml.jackson.annotation.JsonValue
 
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStatus.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkStatus.kt
similarity index 87%
rename from theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStatus.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkStatus.kt
index d4a17dbefb6cf3a53d545c32cb18e1d9acd7067f..691e5e1a83da5ccb3897f0b6342ee78ce437ba6b 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStatus.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkStatus.kt
@@ -1,4 +1,4 @@
-package theodolite.model.crd
+package rocks.theodolite.kubernetes.model.crd
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.fabric8.kubernetes.api.model.KubernetesResource
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionCRD.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionCRD.kt
similarity index 86%
rename from theodolite/src/main/kotlin/theodolite/model/crd/ExecutionCRD.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionCRD.kt
index 3be0aaf2a30cd4ef279edd34854eb936cc6e7e7c..df7b0f0c1ca326db21885beb1c714060aa56b251 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionCRD.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionCRD.kt
@@ -1,4 +1,4 @@
-package theodolite.model.crd
+package rocks.theodolite.kubernetes.model.crd
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.fabric8.kubernetes.api.model.Namespaced
@@ -6,7 +6,7 @@ import io.fabric8.kubernetes.client.CustomResource
 import io.fabric8.kubernetes.model.annotation.Group
 import io.fabric8.kubernetes.model.annotation.Kind
 import io.fabric8.kubernetes.model.annotation.Version
-import theodolite.benchmark.BenchmarkExecution
+import rocks.theodolite.kubernetes.model.BenchmarkExecution
 
 @JsonDeserialize
 @Version("v1")
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionState.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionState.kt
similarity index 86%
rename from theodolite/src/main/kotlin/theodolite/model/crd/ExecutionState.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionState.kt
index 9ce38d9f56a968ccc408966e56609ee4f70570a4..d74d70eb8e91246946923532967534aa46b958f7 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionState.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionState.kt
@@ -1,4 +1,4 @@
-package theodolite.model.crd
+package rocks.theodolite.kubernetes.model.crd
 
 import com.fasterxml.jackson.annotation.JsonValue
 
diff --git a/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStateComparator.kt
similarity index 74%
rename from theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStateComparator.kt
index 81bf350b58901bc10535f143d5ccdb295b5fe85f..9e859c3e943df4c72a2265941f14ea218b35ab12 100644
--- a/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStateComparator.kt
@@ -1,7 +1,7 @@
-package theodolite.util
+package rocks.theodolite.kubernetes.model.crd
 
-import theodolite.model.crd.ExecutionCRD
-import theodolite.model.crd.ExecutionState
+import rocks.theodolite.kubernetes.model.crd.ExecutionCRD
+import rocks.theodolite.kubernetes.model.crd.ExecutionState
 
 class ExecutionStateComparator(private val preferredState: ExecutionState): Comparator<ExecutionCRD> {
 
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStatus.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStatus.kt
similarity index 97%
rename from theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStatus.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStatus.kt
index 1f843ccf9152676e778bc4ed359776e37205e998..6bec7197ddde61185ca37b3e0e96f471a910a0aa 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStatus.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStatus.kt
@@ -1,4 +1,4 @@
-package theodolite.model.crd
+package rocks.theodolite.kubernetes.model.crd
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties
 import com.fasterxml.jackson.core.JsonGenerator
diff --git a/theodolite/src/main/kotlin/theodolite/util/KafkaConfig.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/KafkaConfig.kt
similarity index 92%
rename from theodolite/src/main/kotlin/theodolite/util/KafkaConfig.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/KafkaConfig.kt
index 4e72ccb0d86749a6538c26556241ac114ef8d9a4..adde94c5126e370816966e6991670b6d400ba79a 100644
--- a/theodolite/src/main/kotlin/theodolite/util/KafkaConfig.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/KafkaConfig.kt
@@ -1,8 +1,8 @@
-package theodolite.util
+package rocks.theodolite.kubernetes.model.crd
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.quarkus.runtime.annotations.RegisterForReflection
-import theodolite.util.KafkaConfig.TopicWrapper
+import rocks.theodolite.kubernetes.model.crd.KafkaConfig.TopicWrapper
 import kotlin.properties.Delegates
 import kotlin.reflect.KProperty
 
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/KubernetesBenchmarkList.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/KubernetesBenchmarkList.kt
similarity index 72%
rename from theodolite/src/main/kotlin/theodolite/model/crd/KubernetesBenchmarkList.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/KubernetesBenchmarkList.kt
index 8ad0a493d948bf5f78741052100766dcf6e316ec..be34662bd63b39808099a968ec4b89b5499ef34b 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/KubernetesBenchmarkList.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/KubernetesBenchmarkList.kt
@@ -1,4 +1,4 @@
-package theodolite.model.crd
+package rocks.theodolite.kubernetes.model.crd
 
 import io.fabric8.kubernetes.client.CustomResourceList
 
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/AbstractStateHandler.kt
similarity index 79%
rename from theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/AbstractStateHandler.kt
index 93536282e2eefe6e476c3fde3fd86860fa24dcc3..96593914cf07c427c924a1631a00f76dc3649ed3 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/AbstractStateHandler.kt
@@ -1,4 +1,4 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
 import io.fabric8.kubernetes.api.model.HasMetadata
 import io.fabric8.kubernetes.api.model.KubernetesResourceList
@@ -25,7 +25,12 @@ abstract class AbstractStateHandler<S : HasMetadata>(
             val resource = this.crdClient.withName(resourceName).get()
             if (resource != null) {
                 val resourcePatched = setter(resource)
-                this.crdClient.patchStatus(resourcePatched)
+                // TODO replace with this.crdClient.replaceStatus(resourcePatched) with upcoming fabric8 release (> 5.12.1)
+                // find out the difference between patchStatus and replaceStatus
+                // see also https://github.com/fabric8io/kubernetes-client/pull/3798
+                if (resourcePatched != null) {
+                    this.crdClient.withName(resourcePatched.metadata.name).patchStatus(resourcePatched)
+                }
             }
         } catch (e: KubernetesClientException) {
             logger.warn(e) { "Status cannot be set for resource $resourceName." }
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateChecker.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateChecker.kt
similarity index 85%
rename from theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateChecker.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateChecker.kt
index 6dcfb582655ff9295aedd63d8c30cbac7daae2b3..90229d9533ea69116a460162b8b4046eb0b3aea6 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateChecker.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateChecker.kt
@@ -1,22 +1,23 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
 import io.fabric8.kubernetes.api.model.apps.Deployment
 import io.fabric8.kubernetes.api.model.apps.StatefulSet
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.fabric8.kubernetes.client.dsl.MixedOperation
 import io.fabric8.kubernetes.client.dsl.Resource
-import theodolite.benchmark.Action
-import theodolite.benchmark.ActionSelector
-import theodolite.benchmark.KubernetesBenchmark
-import theodolite.benchmark.ResourceSets
-import theodolite.model.crd.BenchmarkCRD
-import theodolite.model.crd.BenchmarkState
-import theodolite.model.crd.KubernetesBenchmarkList
+import rocks.theodolite.kubernetes.Action
+import rocks.theodolite.kubernetes.ActionSelector
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark
+import rocks.theodolite.kubernetes.ResourceSets
+import rocks.theodolite.kubernetes.model.crd.BenchmarkCRD
+import rocks.theodolite.kubernetes.model.crd.BenchmarkState
+import rocks.theodolite.kubernetes.model.crd.KubernetesBenchmarkList
+import rocks.theodolite.kubernetes.loadKubernetesResources
 
 class BenchmarkStateChecker(
-    private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>,
-    private val benchmarkStateHandler: BenchmarkStateHandler,
-    private val client: NamespacedKubernetesClient
+        private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>,
+        private val benchmarkStateHandler: BenchmarkStateHandler,
+        private val client: NamespacedKubernetesClient,
 
 ) {
 
@@ -129,7 +130,7 @@ class BenchmarkStateChecker(
      * @return true if the required resources are found, else false
      */
     fun checkIfResourceIsInfrastructure(resourcesSets: List<ResourceSets>, selector: ActionSelector): Boolean {
-        val resources = resourcesSets.flatMap { it.loadResourceSet(this.client) }
+        val resources = loadKubernetesResources(resourcesSets, this.client)
         if (resources.isEmpty()) {
             return false
         }
@@ -176,9 +177,9 @@ class BenchmarkStateChecker(
     fun checkResources(benchmark: KubernetesBenchmark): BenchmarkState {
         return try {
             val appResources =
-                benchmark.loadKubernetesResources(resourceSet = benchmark.sut.resources)
+                    loadKubernetesResources(resourceSet = benchmark.sut.resources, this.client)
             val loadGenResources =
-                benchmark.loadKubernetesResources(resourceSet = benchmark.loadGenerator.resources)
+                    loadKubernetesResources(resourceSet = benchmark.loadGenerator.resources, this.client)
             if (appResources.isNotEmpty() && loadGenResources.isNotEmpty()) {
                 BenchmarkState.READY
             } else {
@@ -188,9 +189,11 @@ class BenchmarkStateChecker(
             BenchmarkState.PENDING
         }
     }
+
+
 }
 
-private fun <K, V> MutableMap<K, V>.containsMatchLabels(matchLabels: MutableMap<V, V>): Boolean {
+private fun <K, V> Map<K, V>.containsMatchLabels(matchLabels: Map<V, V>): Boolean {
     for (kv in matchLabels) {
         if (kv.value != this[kv.key as K]) {
             return false
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateHandler.kt
similarity index 80%
rename from theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateHandler.kt
index 3b46859737d86a34b58a5514c0ae31ae215b9c7d..9a272b43f911bf523adf7c64c5ab34793b7a7dc5 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateHandler.kt
@@ -1,7 +1,9 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
-import theodolite.model.crd.*
+import rocks.theodolite.kubernetes.model.crd.BenchmarkCRD
+import rocks.theodolite.kubernetes.model.crd.BenchmarkState
+import rocks.theodolite.kubernetes.model.crd.ExecutionState
 
 class BenchmarkStateHandler(val client: NamespacedKubernetesClient) :
     AbstractStateHandler<BenchmarkCRD>(
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ClusterSetup.kt
similarity index 67%
rename from theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ClusterSetup.kt
index 885315df6eda0d91a27567720056738b997a8ec1..a84bacb8296d62b8d6863046561dc797443e6084 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ClusterSetup.kt
@@ -1,17 +1,21 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
+import io.fabric8.kubernetes.client.KubernetesClientException
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.fabric8.kubernetes.client.dsl.MixedOperation
 import io.fabric8.kubernetes.client.dsl.Resource
-import theodolite.execution.Shutdown
-import theodolite.k8s.K8sContextFactory
-import theodolite.k8s.ResourceByLabelHandler
-import theodolite.model.crd.*
+import mu.KotlinLogging
+import rocks.theodolite.kubernetes.K8sContextFactory
+import rocks.theodolite.kubernetes.ResourceByLabelHandler
+import rocks.theodolite.kubernetes.model.crd.*
+import rocks.theodolite.kubernetes.Shutdown
+
+private val logger = KotlinLogging.logger {}
 
 class ClusterSetup(
-    private val executionCRDClient: MixedOperation<ExecutionCRD, BenchmarkExecutionList, Resource<ExecutionCRD>>,
-    private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>,
-    private val client: NamespacedKubernetesClient
+        private val executionCRDClient: MixedOperation<ExecutionCRD, BenchmarkExecutionList, Resource<ExecutionCRD>>,
+        private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>,
+        private val client: NamespacedKubernetesClient
 
 ) {
     private val serviceMonitorContext = K8sContextFactory().create(
@@ -49,7 +53,7 @@ class ClusterSetup(
                 if (benchmark != null) {
                     execution.spec.name = execution.metadata.name
                     benchmark.spec.name = benchmark.metadata.name
-                    Shutdown(execution.spec, benchmark.spec).run()
+                    Shutdown(execution.spec, benchmark.spec, client).run()
                 } else {
                     throw IllegalStateException("Execution with state ${ExecutionState.RUNNING.value} was found, but no corresponding benchmark. " +
                             "Could not initialize cluster.")
@@ -75,10 +79,15 @@ class ClusterSetup(
             labelName = "app.kubernetes.io/created-by",
             labelValue = "theodolite"
         )
-        resourceRemover.removeCR(
-            labelName = "app.kubernetes.io/created-by",
-            labelValue = "theodolite",
-            context = serviceMonitorContext
-        )
+        try {
+            resourceRemover.removeCR(
+                labelName = "app.kubernetes.io/created-by",
+                labelValue = "theodolite",
+                context = serviceMonitorContext
+            )
+        } catch (e: KubernetesClientException) {
+            logger.warn { "Service monitors could not be cleaned up. It may be that service monitors are not registered by the Kubernetes API."}
+            logger.debug { "Error is: ${e.message}" }
+        }
     }
 }
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/EventCreator.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/EventCreator.kt
similarity index 83%
rename from theodolite/src/main/kotlin/theodolite/execution/operator/EventCreator.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/EventCreator.kt
index fab098ebd5fe765a455d787ddb7fcbfbb6c9ffc7..6803da62f045efcaf1b5504a33b42b2200d16baa 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/EventCreator.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/EventCreator.kt
@@ -1,4 +1,4 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
 import io.fabric8.kubernetes.api.model.EventBuilder
 import io.fabric8.kubernetes.api.model.EventSource
@@ -6,14 +6,14 @@ import io.fabric8.kubernetes.api.model.ObjectReference
 import io.fabric8.kubernetes.client.DefaultKubernetesClient
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import mu.KotlinLogging
-import theodolite.util.Configuration
+import rocks.theodolite.kubernetes.Configuration
 import java.time.Instant
 import java.util.*
 import kotlin.NoSuchElementException
 private val logger = KotlinLogging.logger {}
 
 class EventCreator {
-    val client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(Configuration.NAMESPACE)
+    private val client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(Configuration.NAMESPACE)
 
     fun createEvent(executionName: String, type: String, message: String, reason: String) {
         val uuid = UUID.randomUUID().toString()
@@ -34,15 +34,15 @@ class EventCreator {
             event.source = source
 
             event.involvedObject = objectRef
-            client.v1().events().inNamespace(Configuration.NAMESPACE).createOrReplace(event)
+            this.client.v1().events().inNamespace(Configuration.NAMESPACE).createOrReplace(event)
         } catch (e: NoSuchElementException) {
                 logger.warn {"Could not create event: type: $type, message: $message, reason: $reason, no corresponding execution found."}
         }
     }
 
     private fun buildObjectReference(executionName: String): ObjectReference {
-        val exec = TheodoliteOperator()
-            .getExecutionClient(client = client)
+        val exec = TheodoliteOperator(this.client)
+            .getExecutionClient()
             .list()
             .items
             .first{it.metadata.name == executionName}
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandler.kt
similarity index 91%
rename from theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandler.kt
index 25c627a350e3939530c4b453ec6db846b546cc08..58120d25d7e26daab015c01fece85cf72344bffa 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandler.kt
@@ -1,11 +1,12 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
 import com.google.gson.Gson
 import com.google.gson.GsonBuilder
 import io.fabric8.kubernetes.client.informers.ResourceEventHandler
 import mu.KotlinLogging
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.model.crd.*
+import rocks.theodolite.kubernetes.model.BenchmarkExecution
+import rocks.theodolite.kubernetes.model.crd.ExecutionCRD
+import rocks.theodolite.kubernetes.model.crd.ExecutionState
 
 private val logger = KotlinLogging.logger {}
 
@@ -18,8 +19,8 @@ private val logger = KotlinLogging.logger {}
  * @see BenchmarkExecution
  */
 class ExecutionEventHandler(
-    private val controller: TheodoliteController,
-    private val stateHandler: ExecutionStateHandler
+        private val controller: TheodoliteController,
+        private val stateHandler: ExecutionStateHandler
 ) : ResourceEventHandler<ExecutionCRD> {
 
     private val gson: Gson = GsonBuilder().enableComplexMapKeySerialization().create()
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ExecutionStateHandler.kt
similarity index 92%
rename from theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ExecutionStateHandler.kt
index 340044e5be954d4d7673120e5bf2cba5aed02d92..6264b574d2be297865fab3b2a4d020bc57c56678 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ExecutionStateHandler.kt
@@ -1,9 +1,9 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
 import io.fabric8.kubernetes.api.model.MicroTime
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
-import theodolite.model.crd.ExecutionCRD
-import theodolite.model.crd.ExecutionState
+import rocks.theodolite.kubernetes.model.crd.ExecutionCRD
+import rocks.theodolite.kubernetes.model.crd.ExecutionState
 import java.lang.Thread.sleep
 import java.time.Instant
 import java.util.concurrent.atomic.AtomicBoolean
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/LeaderElector.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/LeaderElector.kt
similarity index 82%
rename from theodolite/src/main/kotlin/theodolite/execution/operator/LeaderElector.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/LeaderElector.kt
index 1ce94c2fdd1ce13d50a21e01b9d4692c87d0da6f..8a713d040e931a0e60266059c4faa44fdf5bddbc 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/LeaderElector.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/LeaderElector.kt
@@ -1,4 +1,4 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
 import io.fabric8.kubernetes.client.DefaultKubernetesClient
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
@@ -18,22 +18,22 @@ class LeaderElector(
 ) {
 
     // TODO(what is the name of the lock? .withName() or LeaseLock(..,name..) ?)
-    fun getLeadership(leader: KFunction0<Unit>) {
+    fun getLeadership(leader: () -> Unit) {
         val lockIdentity: String = UUID.randomUUID().toString()
         DefaultKubernetesClient().use { kc ->
             kc.leaderElector()
                 .withConfig(
                     LeaderElectionConfigBuilder()
                         .withName("Theodolite")
-                        .withLeaseDuration(Duration.ofSeconds(15L))
+                        .withLeaseDuration(Duration.ofSeconds(15))
                         .withLock(LeaseLock(client.namespace, name, lockIdentity))
-                        .withRenewDeadline(Duration.ofSeconds(10L))
-                        .withRetryPeriod(Duration.ofSeconds(2L))
+                        .withRenewDeadline(Duration.ofSeconds(10))
+                        .withRetryPeriod(Duration.ofSeconds(2))
                         .withLeaderCallbacks(LeaderCallbacks(
                             { Thread { leader() }.start() },
-                            { logger.info { "STOPPED LEADERSHIP" } }
+                            { logger.info { "Stop being the leading operator." } }
                         ) { newLeader: String? ->
-                            logger.info { "New leader elected $newLeader" }
+                            logger.info { "New leader elected: $newLeader" }
                         })
                         .build()
                 )
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/StateHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/StateHandler.kt
similarity index 90%
rename from theodolite/src/main/kotlin/theodolite/execution/operator/StateHandler.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/StateHandler.kt
index 28563ac5a640d0226224b812a8e0691cde83942a..eaa3b39ec1391cb1e27573dfc85345add4c32330 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/StateHandler.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/StateHandler.kt
@@ -1,4 +1,4 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
 private const val MAX_RETRIES: Int = 5
 
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/TheodoliteController.kt
similarity index 68%
rename from theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/TheodoliteController.kt
index 5f4180b0b4b58fa94b979c71998314baae63a91b..67a9a40fe260c8105e30fef3c9c44436b7a37c5e 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/TheodoliteController.kt
@@ -1,14 +1,19 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.fabric8.kubernetes.client.dsl.MixedOperation
 import io.fabric8.kubernetes.client.dsl.Resource
 import mu.KotlinLogging
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.benchmark.KubernetesBenchmark
-import theodolite.execution.TheodoliteExecutor
-import theodolite.model.crd.*
-import theodolite.patcher.ConfigOverrideModifier
-import theodolite.util.ExecutionStateComparator
+import rocks.theodolite.kubernetes.model.BenchmarkExecution
+import rocks.theodolite.kubernetes.model.crd.BenchmarkCRD
+import rocks.theodolite.kubernetes.model.crd.ExecutionState
+import rocks.theodolite.kubernetes.model.crd.KubernetesBenchmarkList
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark
+import rocks.theodolite.kubernetes.TheodoliteExecutor
+import rocks.theodolite.kubernetes.model.crd.*
+import rocks.theodolite.kubernetes.patcher.ConfigOverrideModifier
+import rocks.theodolite.kubernetes.model.crd.ExecutionStateComparator
+import rocks.theodolite.kubernetes.loadKubernetesResources
 import java.lang.Thread.sleep
 
 private val logger = KotlinLogging.logger {}
@@ -25,10 +30,12 @@ const val CREATED_BY_LABEL_VALUE = "theodolite"
  */
 
 class TheodoliteController(
-    private val executionCRDClient: MixedOperation<ExecutionCRD, BenchmarkExecutionList, Resource<ExecutionCRD>>,
-    private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>,
-    private val executionStateHandler: ExecutionStateHandler,
-    private val benchmarkStateChecker: BenchmarkStateChecker
+        private val client: NamespacedKubernetesClient,
+        private val executionCRDClient: MixedOperation<ExecutionCRD, BenchmarkExecutionList, Resource<ExecutionCRD>>,
+        private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>,
+        private val executionStateHandler: ExecutionStateHandler,
+        private val benchmarkStateChecker: BenchmarkStateChecker,
+
 ) {
     lateinit var executor: TheodoliteExecutor
 
@@ -68,28 +75,28 @@ class TheodoliteController(
     private fun runExecution(execution: BenchmarkExecution, benchmark: KubernetesBenchmark) {
         try {
             val modifier = ConfigOverrideModifier(
-            execution = execution,
-            resources = benchmark.loadKubernetesResources(benchmark.sut.resources).map { it.first }
-                    + benchmark.loadKubernetesResources(benchmark.loadGenerator.resources).map { it.first }
-        )
-        modifier.setAdditionalLabels(
-            labelValue = execution.name,
-            labelName = DEPLOYED_FOR_EXECUTION_LABEL_NAME
-        )
-        modifier.setAdditionalLabels(
-            labelValue = benchmark.name,
-            labelName = DEPLOYED_FOR_BENCHMARK_LABEL_NAME
-        )
-        modifier.setAdditionalLabels(
-            labelValue = CREATED_BY_LABEL_VALUE,
-            labelName = CREATED_BY_LABEL_NAME
-        )
+                    execution = execution,
+                    resources = loadKubernetesResources(benchmark.sut.resources, this.client).map { it.first }
+                            + loadKubernetesResources(benchmark.loadGenerator.resources, this.client).map { it.first }
+            )
+            modifier.setAdditionalLabels(
+                labelValue = execution.name,
+                labelName = DEPLOYED_FOR_EXECUTION_LABEL_NAME
+            )
+            modifier.setAdditionalLabels(
+                labelValue = benchmark.name,
+                labelName = DEPLOYED_FOR_BENCHMARK_LABEL_NAME
+            )
+            modifier.setAdditionalLabels(
+                labelValue = CREATED_BY_LABEL_VALUE,
+                labelName = CREATED_BY_LABEL_NAME
+            )
 
-        executionStateHandler.setExecutionState(execution.name, ExecutionState.RUNNING)
-        executionStateHandler.startDurationStateTimer(execution.name)
+            executionStateHandler.setExecutionState(execution.name, ExecutionState.RUNNING)
+            executionStateHandler.startDurationStateTimer(execution.name)
 
-            executor = TheodoliteExecutor(execution, benchmark)
-            executor.run()
+            executor = TheodoliteExecutor(execution, benchmark, this.client)
+            executor.setupAndRunExecution()
             when (executionStateHandler.getExecutionState(execution.name)) {
                 ExecutionState.RESTART -> runExecution(execution, benchmark)
                 ExecutionState.RUNNING -> {
@@ -119,7 +126,7 @@ class TheodoliteController(
         if (restart) {
             executionStateHandler.setExecutionState(this.executor.getExecution().name, ExecutionState.RESTART)
         }
-        this.executor.executor.run.set(false)
+        this.executor.experimentRunner.run.set(false)
     }
 
     /**
@@ -130,8 +137,7 @@ class TheodoliteController(
             .list()
             .items
             .map {
-                it.spec.name = it.metadata.name
-                it
+                it.apply { it.spec.name = it.metadata.name }
             }
     }
 
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/TheodoliteOperator.kt
similarity index 61%
rename from theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/TheodoliteOperator.kt
index 071bd06071345499d01595df72e5de4c8535b3fc..bdaa2692d374b4002a1f890f706e2c1ec0d8733c 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/TheodoliteOperator.kt
@@ -1,20 +1,18 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
-import io.fabric8.kubernetes.client.DefaultKubernetesClient
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.fabric8.kubernetes.client.dsl.MixedOperation
 import io.fabric8.kubernetes.client.dsl.Resource
 import io.fabric8.kubernetes.client.informers.SharedInformerFactory
 import io.fabric8.kubernetes.internal.KubernetesDeserializer
 import mu.KotlinLogging
-import theodolite.model.crd.BenchmarkCRD
-import theodolite.model.crd.BenchmarkExecutionList
-import theodolite.model.crd.ExecutionCRD
-import theodolite.model.crd.KubernetesBenchmarkList
-import theodolite.util.Configuration
+import rocks.theodolite.kubernetes.Configuration
+import rocks.theodolite.kubernetes.model.crd.BenchmarkCRD
+import rocks.theodolite.kubernetes.model.crd.BenchmarkExecutionList
+import rocks.theodolite.kubernetes.model.crd.ExecutionCRD
+import rocks.theodolite.kubernetes.model.crd.KubernetesBenchmarkList
 
 
-private const val DEFAULT_NAMESPACE = "default"
 private const val EXECUTION_SINGULAR = "execution"
 private const val BENCHMARK_SINGULAR = "benchmark"
 private const val API_VERSION = "v1"
@@ -27,10 +25,7 @@ private val logger = KotlinLogging.logger {}
  *
  * **See Also:** [Kubernetes Operator Pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)
  */
-class TheodoliteOperator {
-    private val namespace = Configuration.NAMESPACE
-
-    private val client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(namespace)
+class TheodoliteOperator(private val client: NamespacedKubernetesClient) {
     private lateinit var controller: TheodoliteController
     private lateinit var executionStateHandler: ExecutionStateHandler
     private lateinit var benchmarkStateHandler: BenchmarkStateHandler
@@ -39,17 +34,16 @@ class TheodoliteOperator {
 
     fun start() {
         LeaderElector(
-            client = client,
+            client = this.client,
             name = Configuration.COMPONENT_NAME
-        )
-            .getLeadership(::startOperator)
+        ).getLeadership(::startOperator)
     }
 
     /**
      * Start the operator.
      */
     private fun startOperator() {
-        logger.info { "Using $namespace as namespace." }
+        logger.info { "Becoming the leading operator. Use namespace '${this.client.namespace}'." }
         client.use {
             KubernetesDeserializer.registerCustomKind(
                 "$GROUP/$API_VERSION",
@@ -64,28 +58,26 @@ class TheodoliteOperator {
             )
 
             ClusterSetup(
-                executionCRDClient = getExecutionClient(client),
-                benchmarkCRDClient = getBenchmarkClient(client),
-                client = client
+                executionCRDClient = getExecutionClient(),
+                benchmarkCRDClient = getBenchmarkClient(),
+                client = this.client
             ).clearClusterState()
 
             controller = getController(
-                client = client,
-                executionStateHandler = getExecutionStateHandler(client = client),
-                benchmarkStateChecker = getBenchmarkStateChecker(client = client)
+                executionStateHandler = getExecutionStateHandler(),
+                benchmarkStateChecker = getBenchmarkStateChecker()
 
             )
-            getExecutionEventHandler(controller, client).startAllRegisteredInformers()
+            getExecutionEventHandler(controller).startAllRegisteredInformers()
             controller.run()
         }
     }
 
-    fun getExecutionEventHandler(
-        controller: TheodoliteController,
-        client: NamespacedKubernetesClient
+    private fun getExecutionEventHandler(
+            controller: TheodoliteController,
     ): SharedInformerFactory {
-        val factory = client.informers()
-            .inNamespace(client.namespace)
+        val factory = this.client.informers()
+            .inNamespace(this.client.namespace)
 
         factory.sharedIndexInformerForCustomResource(
             ExecutionCRD::class.java,
@@ -93,46 +85,46 @@ class TheodoliteOperator {
         ).addEventHandler(
             ExecutionEventHandler(
                 controller = controller,
-                stateHandler = ExecutionStateHandler(client)
+                stateHandler = ExecutionStateHandler(this.client)
             )
         )
         return factory
     }
 
-    fun getExecutionStateHandler(client: NamespacedKubernetesClient): ExecutionStateHandler {
+    fun getExecutionStateHandler(): ExecutionStateHandler {
         if (!::executionStateHandler.isInitialized) {
-            this.executionStateHandler = ExecutionStateHandler(client = client)
+            this.executionStateHandler = ExecutionStateHandler(client = this.client)
         }
         return executionStateHandler
     }
 
-    fun getBenchmarkStateHandler(client: NamespacedKubernetesClient) : BenchmarkStateHandler {
+    fun getBenchmarkStateHandler() : BenchmarkStateHandler {
         if (!::benchmarkStateHandler.isInitialized) {
-            this.benchmarkStateHandler = BenchmarkStateHandler(client = client)
+            this.benchmarkStateHandler = BenchmarkStateHandler(client = this.client)
         }
         return benchmarkStateHandler
     }
 
-    fun getBenchmarkStateChecker(client: NamespacedKubernetesClient) : BenchmarkStateChecker {
+    fun getBenchmarkStateChecker() : BenchmarkStateChecker {
         if (!::benchmarkStateChecker.isInitialized) {
             this.benchmarkStateChecker = BenchmarkStateChecker(
-                client = client,
-                benchmarkStateHandler = getBenchmarkStateHandler(client = client),
-                benchmarkCRDClient = getBenchmarkClient(client = client))
+                client = this.client,
+                benchmarkStateHandler = getBenchmarkStateHandler(),
+                benchmarkCRDClient = getBenchmarkClient())
         }
         return benchmarkStateChecker
     }
 
 
     fun getController(
-        client: NamespacedKubernetesClient,
-        executionStateHandler: ExecutionStateHandler,
-        benchmarkStateChecker: BenchmarkStateChecker
+            executionStateHandler: ExecutionStateHandler,
+            benchmarkStateChecker: BenchmarkStateChecker
     ): TheodoliteController {
         if (!::controller.isInitialized) {
             this.controller = TheodoliteController(
-                benchmarkCRDClient = getBenchmarkClient(client),
-                executionCRDClient = getExecutionClient(client),
+                client = this.client,
+                benchmarkCRDClient = getBenchmarkClient(),
+                executionCRDClient = getExecutionClient(),
                 executionStateHandler = executionStateHandler,
                 benchmarkStateChecker = benchmarkStateChecker
             )
@@ -140,21 +132,21 @@ class TheodoliteOperator {
         return this.controller
     }
 
-    fun getExecutionClient(client: NamespacedKubernetesClient): MixedOperation<
+    fun getExecutionClient(): MixedOperation<
             ExecutionCRD,
             BenchmarkExecutionList,
             Resource<ExecutionCRD>> {
-        return client.customResources(
+        return this.client.customResources(
             ExecutionCRD::class.java,
             BenchmarkExecutionList::class.java
         )
     }
 
-    fun getBenchmarkClient(client: NamespacedKubernetesClient): MixedOperation<
+    fun getBenchmarkClient(): MixedOperation<
             BenchmarkCRD,
             KubernetesBenchmarkList,
             Resource<BenchmarkCRD>> {
-        return client.customResources(
+        return this.client.customResources(
             BenchmarkCRD::class.java,
             KubernetesBenchmarkList::class.java
         )
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/AbstractPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/AbstractPatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a20a26b351e730de60497ac014b3aba855ac01f5
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/AbstractPatcher.kt
@@ -0,0 +1,30 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.client.utils.Serialization
+
+/**
+ * A Patcher is able to modify values of a Kubernetes resource, see [Patcher].
+ *
+ * An AbstractPatcher is created with up to three parameters.
+ *
+ *
+ *
+ * **For example** to patch the load dimension of a load generator, the patcher should be created as follow:
+ *
+ * k8sResource: `uc-1-workload-generator.yaml`
+ * container: `workload`
+ * variableName: `NUM_SENSORS`
+ *
+ */
+abstract class AbstractPatcher : Patcher {
+
+    override fun patch(resources: List<HasMetadata>, value: String) : List<HasMetadata> {
+        return resources
+            .map { Serialization.clone(it)}
+            .map { patchSingleResource(it, value) }
+    }
+
+    abstract fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata
+
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/ConfigOverrideModifier.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ConfigOverrideModifier.kt
similarity index 89%
rename from theodolite/src/main/kotlin/theodolite/patcher/ConfigOverrideModifier.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ConfigOverrideModifier.kt
index 8f77b1b95f3bf5cc9422cda55cb261048cebaeb6..c45808b5a81e5ffdfa5fd09b263ae49312a8d7fa 100644
--- a/theodolite/src/main/kotlin/theodolite/patcher/ConfigOverrideModifier.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ConfigOverrideModifier.kt
@@ -1,8 +1,7 @@
-package theodolite.patcher
+package rocks.theodolite.kubernetes.patcher
 
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.util.ConfigurationOverride
-import theodolite.util.PatcherDefinition
+import rocks.theodolite.kubernetes.model.BenchmarkExecution
+import rocks.theodolite.kubernetes.util.ConfigurationOverride
 
 /**
  * The ConfigOverrideModifier makes it possible to update the configuration overrides of an execution.
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/DataVolumeLoadGeneratorReplicaPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/DataVolumeLoadGeneratorReplicaPatcher.kt
similarity index 56%
rename from theodolite/src/main/kotlin/theodolite/patcher/DataVolumeLoadGeneratorReplicaPatcher.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/DataVolumeLoadGeneratorReplicaPatcher.kt
index bdc107910edc8ddfb41e7757c775977086a25a26..d884c9ee1b6925bc985ad1da69a46f6589917b01 100644
--- a/theodolite/src/main/kotlin/theodolite/patcher/DataVolumeLoadGeneratorReplicaPatcher.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/DataVolumeLoadGeneratorReplicaPatcher.kt
@@ -1,6 +1,6 @@
-package theodolite.patcher
+package rocks.theodolite.kubernetes.patcher
 
-import io.fabric8.kubernetes.api.model.KubernetesResource
+import io.fabric8.kubernetes.api.model.HasMetadata
 
 /**
  * The DataVolumeLoadGeneratorReplicaPatcher takes the total load that should be generated
@@ -10,29 +10,29 @@ import io.fabric8.kubernetes.api.model.KubernetesResource
  * The number of instances are set for the load generator and the given variable is set to the
  * load per instance.
  *
- * @property k8sResource Kubernetes resource to be patched.
  * @property maxVolume per load generator instance
  * @property container Container to be patched.
  * @property variableName Name of the environment variable to be patched.
  */
 class DataVolumeLoadGeneratorReplicaPatcher(
-    k8sResource: KubernetesResource,
     private val maxVolume: Int,
-    container: String,
-    variableName: String
-) : AbstractPatcher(k8sResource) {
+    private val container: String,
+    private val variableName: String
+) : Patcher {
 
-    private val replicaPatcher = ReplicaPatcher(k8sResource)
-    private val envVarPatcher = EnvVarPatcher(k8sResource, container, variableName)
+    override fun patch(resources: List<HasMetadata>, value: String) : List<HasMetadata> {
+        return resources.flatMap { patchSingeResource(it, value)}
+    }
 
-    override fun <T> patch(value: T) {
+    fun patchSingeResource(k8sResource: HasMetadata, value: String): List<HasMetadata> {
+        var resource = k8sResource
         // calculate number of load generator instances and load per instance
-        val load = Integer.parseInt(value.toString())
+        val load = Integer.parseInt(value)
         val loadGenInstances = (load + maxVolume - 1) / maxVolume
         val loadPerInstance = load / loadGenInstances
 
         // Patch instance values and load value of generators
-        replicaPatcher.patch(loadGenInstances.toString())
-        envVarPatcher.patch(loadPerInstance.toString())
+        val resourceList = ReplicaPatcher().patch(listOf(resource), loadGenInstances.toString())
+        return EnvVarPatcher(this.container, this.variableName).patch(resourceList, loadPerInstance.toString())
     }
 }
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/EnvVarPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/EnvVarPatcher.kt
similarity index 77%
rename from theodolite/src/main/kotlin/theodolite/patcher/EnvVarPatcher.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/EnvVarPatcher.kt
index 416aec74a3af9b74594f5e6cd018682bf91cbf63..33d6c8d9b6f5f82a49e7cd414e4b273708c0e68a 100644
--- a/theodolite/src/main/kotlin/theodolite/patcher/EnvVarPatcher.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/EnvVarPatcher.kt
@@ -1,30 +1,31 @@
-package theodolite.patcher
+package rocks.theodolite.kubernetes.patcher
 
 import io.fabric8.kubernetes.api.model.Container
 import io.fabric8.kubernetes.api.model.EnvVar
-import io.fabric8.kubernetes.api.model.KubernetesResource
+import io.fabric8.kubernetes.api.model.HasMetadata
 import io.fabric8.kubernetes.api.model.apps.Deployment
 
 /**
  * The EnvVarPatcher allows to modify the value of an environment variable
  *
- * @property k8sResource Kubernetes resource to be patched.
  * @property container Container to be patched.
  * @property variableName Name of the environment variable to be patched.
  */
 class EnvVarPatcher(
-    private val k8sResource: KubernetesResource,
     private val container: String,
     private val variableName: String
-) : AbstractPatcher(k8sResource) {
+) : AbstractPatcher() {
 
-    override fun <String> patch(value: String) {
-        if (k8sResource is Deployment) {
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        if (resource is Deployment) {
             this.setEnv(
-                k8sResource, this.container,
-                mapOf(this.variableName to value) as Map<kotlin.String, kotlin.String>
+                resource, this.container,
+                mapOf(this.variableName to value)
             )
+            return resource
         }
+        return resource
     }
 
     /**
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ImagePatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ImagePatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7f54416501bc742499a958566a179b7fad320318
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ImagePatcher.kt
@@ -0,0 +1,37 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.fabric8.kubernetes.api.model.apps.StatefulSet
+import io.fabric8.kubernetes.client.utils.Serialization
+
+/**
+ * The Image patcher allows to change the image of a container.
+ *
+ * @param container Container to be patched.
+ */
+class ImagePatcher(
+    private val container: String) :
+    AbstractPatcher() {
+
+    override fun patch(resources: List<HasMetadata>, value: String) : List<HasMetadata> {
+        return resources
+            .map { Serialization.clone(it) }
+            .map { patchSingleResource(it, value as kotlin.String) }
+    }
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        if (resource is Deployment) {
+            (resource).spec.template.spec.containers.filter { it.name == container }.forEach {
+                it.image = value
+            }
+            return resource
+        } else if (resource is StatefulSet) {
+            (resource).spec.template.spec.containers.filter { it.name == container }.forEach {
+                it.image = value
+            }
+            return resource
+        }
+        return resource
+    }
+}
diff --git a/theodolite/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/InvalidPatcherConfigurationException.kt
similarity index 53%
rename from theodolite/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/InvalidPatcherConfigurationException.kt
index d02948ad341207051c4653ba9400ac0ffe5b03aa..88ad707ec48b0c2c2b3a62cc46f004ced64dbb69 100644
--- a/theodolite/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/InvalidPatcherConfigurationException.kt
@@ -1,3 +1,5 @@
-package theodolite.util
+package rocks.theodolite.kubernetes.patcher
+
+import rocks.theodolite.kubernetes.DeploymentFailedException
 
 class InvalidPatcherConfigurationException(message: String, e: Exception? = null) : DeploymentFailedException(message,e)
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/LabelPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/LabelPatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8bb5be97e780479884e6cb8e551c03340b04f8e6
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/LabelPatcher.kt
@@ -0,0 +1,50 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.ConfigMap
+import io.fabric8.kubernetes.api.model.GenericKubernetesResource
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.api.model.Service
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.fabric8.kubernetes.api.model.apps.StatefulSet
+
+class LabelPatcher(
+    val variableName: String) :
+    AbstractPatcher() {
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        when (resource) {
+            is Deployment -> {
+                if (resource.metadata.labels == null) {
+                    resource.metadata.labels = mutableMapOf()
+                }
+                resource.metadata.labels[this.variableName] = value
+            }
+            is StatefulSet -> {
+                if (resource.metadata.labels == null) {
+                    resource.metadata.labels = mutableMapOf()
+                }
+                resource.metadata.labels[this.variableName] = value
+            }
+            is Service -> {
+                if (resource.metadata.labels == null) {
+                    resource.metadata.labels = mutableMapOf()
+                }
+                resource.metadata.labels[this.variableName] = value
+
+            }
+            is ConfigMap -> {
+                if (resource.metadata.labels == null) {
+                    resource.metadata.labels = mutableMapOf()
+                }
+                resource.metadata.labels[this.variableName] = value
+            }
+            is GenericKubernetesResource -> {
+                if (resource.metadata.labels == null) {
+                    resource.metadata.labels = mutableMapOf()
+                }
+                resource.metadata.labels[this.variableName] = value
+            }
+        }
+        return resource
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/MatchLabelPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/MatchLabelPatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..725c9cf8a6a87c23119812c0a5d5ad3280a42e3c
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/MatchLabelPatcher.kt
@@ -0,0 +1,33 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.fabric8.kubernetes.api.model.apps.StatefulSet
+
+/**
+ * This patcher is able to set the `spec.selector.matchLabels` for a `Deployment` or `StatefulSet` Kubernetes resource.
+ *
+ * @property variableName The matchLabel which should be set
+ */
+class MatchLabelPatcher(
+    val variableName: String) :
+    AbstractPatcher() {
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        when (resource) {
+            is Deployment -> {
+                if (resource.spec.selector.matchLabels == null) {
+                    resource.spec.selector.matchLabels = mutableMapOf()
+                }
+                resource.spec.selector.matchLabels[this.variableName] = value
+            }
+            is StatefulSet -> {
+                if (resource.spec.selector.matchLabels == null) {
+                    resource.spec.selector.matchLabels = mutableMapOf()
+                }
+                resource.spec.selector.matchLabels[this.variableName] = value
+            }
+        }
+        return resource
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NamePatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NamePatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a6416a7e77841fa869de7ce2c248882fb486572c
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NamePatcher.kt
@@ -0,0 +1,35 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.ConfigMap
+import io.fabric8.kubernetes.api.model.GenericKubernetesResource
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.api.model.Service
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.fabric8.kubernetes.api.model.apps.StatefulSet
+
+class NamePatcher : AbstractPatcher() {
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        when (resource) {
+            is Deployment -> {
+                resource.metadata.name = value
+            }
+            is StatefulSet -> {
+                resource.metadata.name = value
+            }
+            is Service -> {
+                resource.metadata.name = value
+            }
+            is ConfigMap -> {
+                resource.metadata.name = value
+            }
+            is io.fabric8.kubernetes.api.model.networking.v1.Ingress -> {
+                resource.metadata.name = value
+            }
+            is GenericKubernetesResource -> {
+                resource.metadata.name = value
+            }
+        }
+        return resource
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NodeSelectorPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NodeSelectorPatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c3b5ba1a07afa41dd604f2335baf6b58e362f293
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NodeSelectorPatcher.kt
@@ -0,0 +1,22 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.api.model.apps.Deployment
+
+/**
+ * The Node selector patcher make it possible to set the NodeSelector of a Kubernetes deployment.
+ *
+ * @param variableName The `label-key` of the node for which the `label-value` is to be patched.
+ */
+class NodeSelectorPatcher(
+    private val variableName: String) :
+    AbstractPatcher() {
+
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        if (resource is Deployment) {
+            resource.spec.template.spec.nodeSelector = mapOf(variableName to value)
+        }
+        return resource
+    }
+}
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e3b0105768ec339758fd89233a09da233145d641
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt
@@ -0,0 +1,23 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import kotlin.math.pow
+
+class NumNestedGroupsLoadGeneratorReplicaPatcher(
+    private val numSensors: String,
+    private val loadGenMaxRecords: String,
+) : AbstractPatcher() {
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        if (resource is Deployment) {
+            val approxNumSensors = numSensors.toDouble().pow(Integer.parseInt(value).toDouble())
+            val loadGenInstances =
+                (approxNumSensors + loadGenMaxRecords.toDouble() - 1) / loadGenMaxRecords.toDouble()
+            resource.spec.replicas = loadGenInstances.toInt()
+
+        }
+        return resource
+    }
+}
+
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6bb2750bb1ca923aa05022884ef7054772a987c6
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt
@@ -0,0 +1,21 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.api.model.apps.Deployment
+
+
+class NumSensorsLoadGeneratorReplicaPatcher(
+    private val loadGenMaxRecords: String,
+) : AbstractPatcher() {
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        if (resource is Deployment) {
+            val loadGenInstances =
+                (Integer.parseInt(value) + loadGenMaxRecords.toInt() - 1) / loadGenMaxRecords.toInt()
+            resource.spec.replicas = loadGenInstances
+
+        }
+        return resource
+    }
+
+}
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatchHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatchHandler.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6873d9ec84cd02b85b2342bbd37d429c706a47ab
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatchHandler.kt
@@ -0,0 +1,20 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.HasMetadata
+class PatchHandler {
+    companion object {
+        private fun getResourcesToPatch(resources: MutableMap<String, List<HasMetadata>>, patcherDefinition: PatcherDefinition): List<HasMetadata> {
+            return resources[patcherDefinition.resource]
+                ?: throw InvalidPatcherConfigurationException("Could not find resource ${patcherDefinition.resource}")
+
+        }
+        fun patchResource(
+            resources: MutableMap<String, List<HasMetadata>>,
+            patcherDefinition: PatcherDefinition,
+            value: String,
+        ): List<HasMetadata> {
+            val resToPatch = getResourcesToPatch(resources, patcherDefinition)
+            return PatcherFactory.createPatcher(patcherDefinition).patch(resToPatch,value)
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/Patcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/Patcher.kt
similarity index 68%
rename from theodolite/src/main/kotlin/theodolite/patcher/Patcher.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/Patcher.kt
index 84b886cb4f06b3e667eb8b8aeaa622e1ee54852e..310b370b97d065fc1ea0c3f7edd81577816ff69c 100644
--- a/theodolite/src/main/kotlin/theodolite/patcher/Patcher.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/Patcher.kt
@@ -1,5 +1,6 @@
-package theodolite.patcher
+package rocks.theodolite.kubernetes.patcher
 
+import io.fabric8.kubernetes.api.model.HasMetadata
 import io.quarkus.runtime.annotations.RegisterForReflection
 
 /**
@@ -13,8 +14,7 @@ interface Patcher {
      * The patch method modifies a value in the definition of a
      * Kubernetes resource.
      *
-     * @param T The type of value
      * @param value The value to be used.
      */
-    fun <T> patch(value: T)
+    fun patch(resources: List<HasMetadata>, value: String) : List<HasMetadata>
 }
diff --git a/theodolite/src/main/kotlin/theodolite/util/PatcherDefinition.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinition.kt
similarity index 86%
rename from theodolite/src/main/kotlin/theodolite/util/PatcherDefinition.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinition.kt
index 6ec0cce36751ec0343d40aa49fefa44f4c7fc918..653ed9e03caf86c661e6a52ed59501b478eea7b5 100644
--- a/theodolite/src/main/kotlin/theodolite/util/PatcherDefinition.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinition.kt
@@ -1,4 +1,4 @@
-package theodolite.util
+package rocks.theodolite.kubernetes.patcher
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import com.fasterxml.jackson.databind.annotation.JsonSerialize
@@ -21,5 +21,5 @@ class PatcherDefinition {
     lateinit var resource: String
 
     @JsonSerialize
-    lateinit var properties: MutableMap<String, String>
+    lateinit var properties: Map<String, String>
 }
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/PatcherDefinitionFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinitionFactory.kt
similarity index 83%
rename from theodolite/src/main/kotlin/theodolite/patcher/PatcherDefinitionFactory.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinitionFactory.kt
index 6a1f993e2ac327ec242a8a5bafc3e6cc43475710..be9dcd11b08edf58462f0a1e71c7c3ab548fa66a 100644
--- a/theodolite/src/main/kotlin/theodolite/patcher/PatcherDefinitionFactory.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinitionFactory.kt
@@ -1,7 +1,6 @@
-package theodolite.patcher
+package rocks.theodolite.kubernetes.patcher
 
-import theodolite.util.PatcherDefinition
-import theodolite.util.TypeName
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark
 
 /**
  * The PatcherDefinition Factory creates a [PatcherDefinition]s.
@@ -20,7 +19,7 @@ class PatcherDefinitionFactory {
      * @return A list of PatcherDefinitions which corresponds to the
      *     value of the requiredType.
      */
-    fun createPatcherDefinition(requiredType: String, patcherTypes: List<TypeName>): List<PatcherDefinition> {
+    fun createPatcherDefinition(requiredType: String, patcherTypes: List<KubernetesBenchmark.TypeName>): List<PatcherDefinition> {
         return patcherTypes.firstOrNull { type -> type.typeName == requiredType }
             ?.patchers ?: throw IllegalArgumentException("typeName $requiredType not found.")
     }
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a4dcf68d2b4ec12facb26755e9f63e298725e195
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt
@@ -0,0 +1,89 @@
+package rocks.theodolite.kubernetes.patcher
+
+/**
+ * The Patcher factory creates [Patcher]s
+ *
+ * @constructor Creates an empty PatcherFactory.
+ */
+class PatcherFactory {
+
+    companion object {
+        /**
+         * Create patcher based on the given [PatcherDefinition] and
+         * the list of KubernetesResources.
+         *
+         * @param patcherDefinition The [PatcherDefinition] for which are
+         *     [Patcher] should be created.
+         * @param k8sResources List of all available Kubernetes resources.
+         *     This is a list of pairs<String, KubernetesResource>:
+         *     The frist corresponds to the filename where the resource is defined.
+         *     The second corresponds to the concrete [KubernetesResource] that should be patched.
+         * @return The created [Patcher].
+         * @throws IllegalArgumentException if no patcher can be created.
+         */
+        fun createPatcher(
+            patcherDefinition: PatcherDefinition,
+        ): Patcher {
+
+            return try {
+                when (patcherDefinition.type) {
+                    "ReplicaPatcher" -> ReplicaPatcher(
+                    )
+                    "NumNestedGroupsLoadGeneratorReplicaPatcher" -> NumNestedGroupsLoadGeneratorReplicaPatcher(
+                        loadGenMaxRecords = patcherDefinition.properties["loadGenMaxRecords"]!!,
+                        numSensors = patcherDefinition.properties["numSensors"]!!
+                    )
+                    "NumSensorsLoadGeneratorReplicaPatcher" -> NumSensorsLoadGeneratorReplicaPatcher(
+                        loadGenMaxRecords = patcherDefinition.properties["loadGenMaxRecords"]!!
+                    )
+                    "DataVolumeLoadGeneratorReplicaPatcher" -> DataVolumeLoadGeneratorReplicaPatcher(
+                        maxVolume = patcherDefinition.properties["maxVolume"]!!.toInt(),
+                        container = patcherDefinition.properties["container"]!!,
+                        variableName = patcherDefinition.properties["variableName"]!!
+                    )
+                    "EnvVarPatcher" -> EnvVarPatcher(
+                        container = patcherDefinition.properties["container"]!!,
+                        variableName = patcherDefinition.properties["variableName"]!!
+                    )
+                    "NodeSelectorPatcher" -> NodeSelectorPatcher(
+                        variableName = patcherDefinition.properties["variableName"]!!
+                    )
+                    "ResourceLimitPatcher" -> ResourceLimitPatcher(
+                        container = patcherDefinition.properties["container"]!!,
+                        limitedResource = patcherDefinition.properties["limitedResource"]!!
+                    )
+                    "ResourceRequestPatcher" -> ResourceRequestPatcher(
+                        container = patcherDefinition.properties["container"]!!,
+                        requestedResource = patcherDefinition.properties["requestedResource"]!!
+                    )
+                    "SchedulerNamePatcher" -> SchedulerNamePatcher()
+                    "LabelPatcher" -> LabelPatcher(
+                        variableName = patcherDefinition.properties["variableName"]!!
+                    )
+                    "MatchLabelPatcher" -> MatchLabelPatcher(
+                        variableName = patcherDefinition.properties["variableName"]!!
+                    )
+                    "TemplateLabelPatcher" -> TemplateLabelPatcher(
+                        variableName = patcherDefinition.properties["variableName"]!!
+                    )
+                    "ImagePatcher" -> ImagePatcher(
+                        container = patcherDefinition.properties["container"]!!
+                    )
+                    "NamePatcher" -> NamePatcher()
+                    "ServiceSelectorPatcher" -> ServiceSelectorPatcher(
+                        variableName = patcherDefinition.properties["label"]!!
+                    )
+                    "rocks.theodolite.kubernetes.patcher.VolumesConfigMapPatcher" -> VolumesConfigMapPatcher(
+                        volumeName = patcherDefinition.properties["volumeName"]!!
+                    )
+                    else -> throw InvalidPatcherConfigurationException("Patcher type ${patcherDefinition.type} not found.")
+                }
+            } catch (e: NullPointerException) {
+                throw InvalidPatcherConfigurationException(
+                    "Could not create patcher with type ${patcherDefinition.type}" +
+                            " Probably a required patcher argument was not specified.", e
+                )
+            }
+        }
+    }
+}
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ReplicaPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ReplicaPatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8637b1299e878c4424e7fcaf4eac3bc901428541
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ReplicaPatcher.kt
@@ -0,0 +1,18 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.api.model.apps.Deployment
+
+/**
+ * The Replica [Patcher] modifies the number of replicas for the given Kubernetes deployment.
+ *
+ */
+class ReplicaPatcher : AbstractPatcher() {
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        if (resource is Deployment) {
+            resource.spec.replicas = Integer.parseInt(value)
+        }
+        return resource
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcher.kt
similarity index 62%
rename from theodolite/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcher.kt
index 9dcdffa0407dd4fdaf2d9b0a898bcdf6cebe5a8b..7450e2edfa20f570742fe0336d0d27c76ec83aa2 100644
--- a/theodolite/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcher.kt
@@ -1,12 +1,8 @@
-package theodolite.patcher
+package rocks.theodolite.kubernetes.patcher
 
-import io.fabric8.kubernetes.api.model.Container
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.api.model.Quantity
-import io.fabric8.kubernetes.api.model.ResourceRequirements
+import io.fabric8.kubernetes.api.model.*
 import io.fabric8.kubernetes.api.model.apps.Deployment
 import io.fabric8.kubernetes.api.model.apps.StatefulSet
-import theodolite.util.InvalidPatcherConfigurationException
 
 /**
  * The Resource limit [Patcher] set resource limits for deployments and statefulSets.
@@ -16,30 +12,31 @@ import theodolite.util.InvalidPatcherConfigurationException
  * @param limitedResource The resource to be limited (e.g. **cpu or memory**)
  */
 class ResourceLimitPatcher(
-    private val k8sResource: KubernetesResource,
     private val container: String,
     private val limitedResource: String
-) : AbstractPatcher(k8sResource) {
+) : AbstractPatcher() {
 
-    override fun <String> patch(value: String) {
-        when (k8sResource) {
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        when (resource) {
             is Deployment -> {
-                k8sResource.spec.template.spec.containers.filter { it.name == container }.forEach {
-                    setLimits(it, value as kotlin.String)
+                resource.spec.template.spec.containers.filter { it.name == container }.forEach {
+                    setLimits(it, value)
                 }
             }
             is StatefulSet -> {
-                k8sResource.spec.template.spec.containers.filter { it.name == container }.forEach {
-                    setLimits(it, value as kotlin.String)
+                resource.spec.template.spec.containers.filter { it.name == container }.forEach {
+                    setLimits(it, value)
                 }
             }
             else -> {
-                throw InvalidPatcherConfigurationException("ResourceLimitPatcher not applicable for $k8sResource")
+                throw InvalidPatcherConfigurationException("ResourceLimitPatcher is not applicable for $resource")
             }
         }
+        return resource
     }
 
-    private fun setLimits(container: Container, value: String) {
+
+        private fun setLimits(container: Container, value: String) {
         when {
             container.resources == null -> {
                 val resource = ResourceRequirements()
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/ResourceRequestPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcher.kt
similarity index 62%
rename from theodolite/src/main/kotlin/theodolite/patcher/ResourceRequestPatcher.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcher.kt
index 24cdde40f7f78bd67d115b2dc44f47e180f51ee2..bdcdc9527e8fa4dad9f85917be7d5c1c2fe67c2e 100644
--- a/theodolite/src/main/kotlin/theodolite/patcher/ResourceRequestPatcher.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcher.kt
@@ -1,44 +1,39 @@
-package theodolite.patcher
+package rocks.theodolite.kubernetes.patcher
 
-import io.fabric8.kubernetes.api.model.Container
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.api.model.Quantity
-import io.fabric8.kubernetes.api.model.ResourceRequirements
+import io.fabric8.kubernetes.api.model.*
 import io.fabric8.kubernetes.api.model.apps.Deployment
 import io.fabric8.kubernetes.api.model.apps.StatefulSet
-import theodolite.util.InvalidPatcherConfigurationException
 
 /**
  * The Resource request [Patcher] set resource limits for deployments and statefulSets.
  *
- * @param k8sResource Kubernetes resource to be patched.
  * @param container Container to be patched.
  * @param requestedResource The resource to be requested (e.g. **cpu or memory**)
  */
 class ResourceRequestPatcher(
-    private val k8sResource: KubernetesResource,
     private val container: String,
     private val requestedResource: String
-) : AbstractPatcher(k8sResource) {
+) : AbstractPatcher() {
 
-    override fun <String> patch(value: String) {
-        when (k8sResource) {
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        when (resource) {
             is Deployment -> {
-                k8sResource.spec.template.spec.containers.filter { it.name == container }.forEach {
-                    setRequests(it, value as kotlin.String)
+                resource.spec.template.spec.containers.filter { it.name == container }.forEach {
+                    setRequests(it, value)
                 }
             }
             is StatefulSet -> {
-                k8sResource.spec.template.spec.containers.filter { it.name == container }.forEach {
-                    setRequests(it, value as kotlin.String)
+                resource.spec.template.spec.containers.filter { it.name == container }.forEach {
+                    setRequests(it, value)
                 }
             }
             else -> {
-                throw InvalidPatcherConfigurationException("ResourceRequestPatcher not applicable for $k8sResource")
+                throw InvalidPatcherConfigurationException("ResourceRequestPatcher is not applicable for $resource")
             }
         }
+        return resource
     }
-
     private fun setRequests(container: Container, value: String) {
         when {
             container.resources == null -> {
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/SchedulerNamePatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/SchedulerNamePatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c5ac16cdfe25f6b2fd2e4d0a2fb27000f885ffe7
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/SchedulerNamePatcher.kt
@@ -0,0 +1,20 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.api.model.apps.Deployment
+
+/**
+ * The Scheduler name [Patcher] make it possible to set the scheduler which should
+ * be used to deploy the given deployment.
+ * @param k8sResource Kubernetes resource to be patched.
+ */
+class SchedulerNamePatcher : AbstractPatcher() {
+
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        if (resource is Deployment) {
+            resource.spec.template.spec.schedulerName = value
+        }
+        return resource
+    }
+}
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ServiceSelectorPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ServiceSelectorPatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b38ae4108748f85e7ac60f3ee3aa8c5d28281432
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ServiceSelectorPatcher.kt
@@ -0,0 +1,19 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.api.model.Service
+
+class ServiceSelectorPatcher(
+    private var variableName: String
+    ) : AbstractPatcher() {
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        if (resource is Service) {
+            if (resource.spec.selector == null) {
+                resource.spec.selector = mutableMapOf()
+            }
+            resource.spec.selector[this.variableName] = value
+        }
+        return resource
+    }
+    }
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/TemplateLabelPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/TemplateLabelPatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..534809cf8c36fb2065cbe3c0823294b346ac05f6
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/TemplateLabelPatcher.kt
@@ -0,0 +1,34 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.fabric8.kubernetes.api.model.apps.StatefulSet
+
+/**
+ * This patcher is able to set the field `spec.template.metadata.labels` for a `Deployment` or `StatefulSet` Kubernetes resource.
+ *
+ * @property variableName The label which should be set
+ */
+class TemplateLabelPatcher(
+    val variableName: String) :
+    AbstractPatcher() {
+
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        when (resource) {
+            is Deployment -> {
+                if (resource.spec.template.metadata.labels == null) {
+                    resource.spec.template.metadata.labels = mutableMapOf()
+                }
+                resource.spec.template.metadata.labels[this.variableName] = value
+            }
+            is StatefulSet -> {
+                if (resource.spec.template.metadata.labels == null) {
+                    resource.spec.template.metadata.labels = mutableMapOf()
+                }
+                resource.spec.template.metadata.labels[this.variableName] = value
+            }
+        }
+        return resource
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/VolumesConfigMapPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/VolumesConfigMapPatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..54a459a19b35e74839de647761e8ac22f839ca2d
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/VolumesConfigMapPatcher.kt
@@ -0,0 +1,44 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.fabric8.kubernetes.api.model.apps.StatefulSet
+
+class VolumesConfigMapPatcher(private var volumeName: String
+) : AbstractPatcher() {
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+        if (resource is Deployment) {
+            if (resource.spec.template.spec.volumes == null) {
+                resource.spec.template.spec.volumes = mutableListOf()
+            }
+            val volumeMounts = resource.spec.template.spec.volumes
+
+            for (mount in volumeMounts) {
+                try {
+                    if (mount.configMap.name == volumeName) {
+                        mount.configMap.name = value
+                    }
+                } catch (_: NullPointerException) {
+                }
+            }
+        }
+        if (resource is StatefulSet) {
+            if (resource.spec.template.spec.volumes == null) {
+                resource.spec.template.spec.volumes = mutableListOf()
+            }
+            val volumeMounts = resource.spec.template.spec.volumes
+
+            for (mount in volumeMounts) {
+                try {
+                    if (mount.configMap.name == volumeName) {
+                        mount.configMap.name = value
+                    }
+                } catch (_: NullPointerException) {
+                }
+            }
+        }
+
+        return resource
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/AnalysisExecutor.kt
similarity index 74%
rename from theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/AnalysisExecutor.kt
index be3e48be406b631e03ca2fd32909a442b592f259..96c5a43b85c0db5600d813f9e799903927a53ec3 100644
--- a/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/AnalysisExecutor.kt
@@ -1,10 +1,8 @@
-package theodolite.evaluation
+package rocks.theodolite.kubernetes.slo
 
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.util.EvaluationFailedException
-import theodolite.util.IOHandler
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
+import rocks.theodolite.core.strategies.Metric
+import rocks.theodolite.core.IOHandler
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark.Slo
 import java.text.Normalizer
 import java.time.Duration
 import java.time.Instant
@@ -16,8 +14,8 @@ import java.util.regex.Pattern
  * @param slo Slo that is used for the analysis.
  */
 class AnalysisExecutor(
-    private val slo: BenchmarkExecution.Slo,
-    private val executionId: Int
+        private val slo: Slo,
+        private val executionId: Int
 ) {
 
     private val fetcher = MetricFetcher(
@@ -29,17 +27,17 @@ class AnalysisExecutor(
      *  Analyses an experiment via prometheus data.
      *  First fetches data from prometheus, then documents them and afterwards evaluate it via a [slo].
      *  @param load of the experiment.
-     *  @param res of the experiment.
+     *  @param resource of the experiment.
      *  @param executionIntervals list of start and end points of experiments
      *  @return true if the experiment succeeded.
      */
-    fun analyze(load: LoadDimension, res: Resource, executionIntervals: List<Pair<Instant, Instant>>): Boolean {
+    fun analyze(load: Int, resource: Int, executionIntervals: List<Pair<Instant, Instant>>, metric: Metric): Boolean {
         var repetitionCounter = 1
 
         try {
             val ioHandler = IOHandler()
-            val resultsFolder: String = ioHandler.getResultFolderURL()
-            val fileURL = "${resultsFolder}exp${executionId}_${load.get()}_${res.get()}_${slo.sloType.toSlug()}"
+            val resultsFolder = ioHandler.getResultFolderURL()
+            val fileURL = "${resultsFolder}exp${executionId}_${load}_${resource}_${slo.sloType.toSlug()}"
 
             val prometheusData = executionIntervals
                 .map { interval ->
@@ -50,9 +48,9 @@ class AnalysisExecutor(
                     )
                 }
 
-            prometheusData.forEach { data ->
+            prometheusData.forEach{ data ->
                 ioHandler.writeToCSVFile(
-                    fileURL = "${fileURL}_${repetitionCounter++}",
+                    fileURL = "${fileURL}_${slo.name}_${repetitionCounter++}",
                     data = data.getResultAsList(),
                     columns = listOf("labels", "timestamp", "value")
                 )
@@ -61,13 +59,15 @@ class AnalysisExecutor(
             val sloChecker = SloCheckerFactory().create(
                 sloType = slo.sloType,
                 properties = slo.properties,
-                load = load
+                load = load,
+                resource = resource,
+                metric = metric
             )
 
             return sloChecker.evaluate(prometheusData)
 
         } catch (e: Exception) {
-            throw EvaluationFailedException("Evaluation failed for resource '${res.get()}' and load '${load.get()}", e)
+            throw EvaluationFailedException("Evaluation failed for resource '$resource' and load '$load ", e)
         }
     }
 
diff --git a/theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/EvaluationFailedException.kt
similarity index 52%
rename from theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/EvaluationFailedException.kt
index ebdf5a37b4e82c8d4b1870d065f5e77133154735..564ec926aeba501c55675ba3d25cfa8ebf50b68b 100644
--- a/theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/EvaluationFailedException.kt
@@ -1,3 +1,5 @@
-package theodolite.util
+package rocks.theodolite.kubernetes.slo
+
+import rocks.theodolite.kubernetes.ExecutionFailedException
 
 class EvaluationFailedException(message: String, e: Exception? = null) : ExecutionFailedException(message,e)
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/ExternalSloChecker.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/ExternalSloChecker.kt
similarity index 91%
rename from theodolite/src/main/kotlin/theodolite/evaluation/ExternalSloChecker.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/ExternalSloChecker.kt
index 7fb5417e200f64b0db74a8bebe69a751c5d484b8..01b21c845a614ba42581c182d975da5ad645b474 100644
--- a/theodolite/src/main/kotlin/theodolite/evaluation/ExternalSloChecker.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/ExternalSloChecker.kt
@@ -1,8 +1,8 @@
-package theodolite.evaluation
+package rocks.theodolite.kubernetes.slo
 
 import khttp.post
 import mu.KotlinLogging
-import theodolite.util.PrometheusResponse
+import rocks.theodolite.kubernetes.util.PrometheusResponse
 import java.net.ConnectException
 
 /**
@@ -40,7 +40,7 @@ class ExternalSloChecker(
             val result = post(externalSlopeURL, data = data, timeout = TIMEOUT)
             if (result.statusCode != 200) {
                 counter++
-                logger.error { "Could not reach external SLO checker." }
+                logger.error { "Could not reach external SLO checker at $externalSlopeURL." }
             } else {
                 val booleanResult = result.text.toBoolean()
                 logger.info { "SLO checker result is: $booleanResult." }
@@ -48,6 +48,6 @@ class ExternalSloChecker(
             }
         }
 
-        throw ConnectException("Could not reach external SLO checker")
+        throw ConnectException("Could not reach external SLO checker at $externalSlopeURL.")
     }
 }
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/MetricFetcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/MetricFetcher.kt
similarity index 88%
rename from theodolite/src/main/kotlin/theodolite/evaluation/MetricFetcher.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/MetricFetcher.kt
index e54d79fe0f95b9f6079bd4295a74e81250b73a90..962564475d0ad0b56bad8cf99daf12329950eaf3 100644
--- a/theodolite/src/main/kotlin/theodolite/evaluation/MetricFetcher.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/MetricFetcher.kt
@@ -1,10 +1,10 @@
-package theodolite.evaluation
+package rocks.theodolite.kubernetes.slo
 
 import com.google.gson.Gson
 import khttp.get
 import khttp.responses.Response
 import mu.KotlinLogging
-import theodolite.util.PrometheusResponse
+import rocks.theodolite.kubernetes.util.PrometheusResponse
 import java.net.ConnectException
 import java.time.Duration
 import java.time.Instant
@@ -45,15 +45,16 @@ class MetricFetcher(private val prometheusURL: String, private val offset: Durat
         )
 
         while (counter < RETRIES) {
+            logger.info { "Request collected metrics from Prometheus for interval [$offsetStart,$offsetEnd]." }
             val response = get("$prometheusURL/api/v1/query_range", params = parameter, timeout = TIMEOUT)
             if (response.statusCode != 200) {
                 val message = response.jsonObject.toString()
-                logger.warn { "Could not connect to Prometheus: $message. Retrying now." }
+                logger.warn { "Could not connect to Prometheus: $message. Retry $counter/$RETRIES." }
                 counter++
             } else {
                 val values = parseValues(response)
                 if (values.data?.result.isNullOrEmpty()) {
-                    throw NoSuchFieldException("Empty query result: $values between $start and $end for query $query.")
+                    throw NoSuchFieldException("Empty query result: $values between for query '$query' in interval [$offsetStart,$offsetEnd] .")
                 }
                 return parseValues(response)
             }
diff --git a/theodolite/src/main/kotlin/theodolite/util/PrometheusResponse.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/PrometheusResponse.kt
similarity index 98%
rename from theodolite/src/main/kotlin/theodolite/util/PrometheusResponse.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/PrometheusResponse.kt
index 9b0b0dd4e0a5a48072ca576e874cb850c5f8df3b..5222a78bde342fea4a94c69bf1e42e132d0bc706 100644
--- a/theodolite/src/main/kotlin/theodolite/util/PrometheusResponse.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/PrometheusResponse.kt
@@ -1,4 +1,4 @@
-package theodolite.util
+package rocks.theodolite.kubernetes.util
 
 import io.quarkus.runtime.annotations.RegisterForReflection
 import java.util.*
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloChecker.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloChecker.kt
similarity index 81%
rename from theodolite/src/main/kotlin/theodolite/evaluation/SloChecker.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloChecker.kt
index 82f903f5be868731d58ebefd6279d5d438bd5eab..f4ac163547421d5f0f07d2511c2e3eeeebdb35b0 100644
--- a/theodolite/src/main/kotlin/theodolite/evaluation/SloChecker.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloChecker.kt
@@ -1,6 +1,6 @@
-package theodolite.evaluation
+package rocks.theodolite.kubernetes.slo
 
-import theodolite.util.PrometheusResponse
+import rocks.theodolite.kubernetes.util.PrometheusResponse
 
 /**
  * A SloChecker can be used to evaluate data from Prometheus.
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloCheckerFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloCheckerFactory.kt
similarity index 95%
rename from theodolite/src/main/kotlin/theodolite/evaluation/SloCheckerFactory.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloCheckerFactory.kt
index f57cebfcb13d0e86919ec15a0a479d1258e318a6..810675f159169f31314289d08a59fcc15bf8a243 100644
--- a/theodolite/src/main/kotlin/theodolite/evaluation/SloCheckerFactory.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloCheckerFactory.kt
@@ -1,6 +1,7 @@
-package theodolite.evaluation
+package rocks.theodolite.kubernetes.slo
+
+import rocks.theodolite.core.strategies.Metric
 
-import theodolite.util.LoadDimension
 
 /**
  * Factory used to potentially create different [SloChecker]s.
@@ -41,7 +42,9 @@ class SloCheckerFactory {
     fun create(
         sloType: String,
         properties: MutableMap<String, String>,
-        load: LoadDimension
+        load: Int,
+        resource: Int,
+        metric: Metric
     ): SloChecker {
         return when (SloTypes.from(sloType)) {
             SloTypes.GENERIC -> ExternalSloChecker(
@@ -76,7 +79,7 @@ class SloCheckerFactory {
                     throw IllegalArgumentException("Threshold ratio needs to be an Double greater or equal 0.0")
                 }
                 // cast to int, as rounding is not really necessary
-                val threshold = (load.get() * thresholdRatio).toInt()
+                val threshold = (load * thresholdRatio).toInt()
 
                 ExternalSloChecker(
                     externalSlopeURL = properties["externalSloUrl"]
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloConfigHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloConfigHandler.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ed18e4a0b4027ce4284cc83ff4c9520738ec2ba7
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloConfigHandler.kt
@@ -0,0 +1,28 @@
+package rocks.theodolite.kubernetes.slo
+
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark.Slo
+import rocks.theodolite.kubernetes.patcher.InvalidPatcherConfigurationException
+import javax.enterprise.context.ApplicationScoped
+
+private const val DEFAULT_CONSUMER_LAG_METRIC_BASE = "kafka_consumergroup_lag"
+private const val DEFAULT_CONSUMER_LAG_QUERY = "sum by(consumergroup) (kafka_consumergroup_lag >= 0)"
+private const val DEFAULT_DROPPED_RECORDS_QUERY = "sum by(job) (kafka_streams_stream_task_metrics_dropped_records_total>=0)"
+
+@ApplicationScoped
+class SloConfigHandler {
+    companion object {
+        fun getQueryString(slo: Slo): String {
+            return when (slo.sloType.lowercase()) {
+                SloTypes.GENERIC.value -> slo.properties["promQLQuery"] ?: throw IllegalArgumentException("promQLQuery expected")
+                SloTypes.LAG_TREND.value, SloTypes.LAG_TREND_RATIO.value -> slo.properties["promQLQuery"] ?:
+                    (slo.properties["consumerGroup"]?.let { "{consumergroup='$it'}" } ?: "").let {
+                        "sum by(consumergroup) ($DEFAULT_CONSUMER_LAG_METRIC_BASE$it >= 0)"
+                    }
+                SloTypes.DROPPED_RECORDS.value, SloTypes.DROPPED_RECORDS_RATIO.value -> slo.properties["promQLQuery"] ?: DEFAULT_DROPPED_RECORDS_QUERY
+                SloTypes.LAG_TREND.value, SloTypes.LAG_TREND_RATIO.value -> slo.properties["promQLQuery"] ?: DEFAULT_CONSUMER_LAG_QUERY
+                SloTypes.DROPPED_RECORDS.value, SloTypes.DROPPED_RECORDS_RATIO.value -> slo.properties["promQLQuery"] ?: DEFAULT_DROPPED_RECORDS_QUERY
+                else -> throw  InvalidPatcherConfigurationException("Could not find Prometheus query string for slo type ${slo.sloType}")
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloFactory.kt
new file mode 100644
index 0000000000000000000000000000000000000000..047f8a657de8aba6f032d36e8b84d7046d5e0209
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloFactory.kt
@@ -0,0 +1,24 @@
+package rocks.theodolite.kubernetes.slo
+
+import rocks.theodolite.kubernetes.model.BenchmarkExecution
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark.Slo
+
+class SloFactory {
+
+    fun createSlos(execution: BenchmarkExecution, benchmark: KubernetesBenchmark): List<Slo> {
+        var benchmarkSlos = benchmark.slos
+        var executionSlos = execution.slos
+
+        for(executionSlo in executionSlos) {
+            for(i in 0 until benchmarkSlos.size) {
+                if(executionSlo.name == benchmarkSlos[i].name && executionSlo.properties != null) {
+                    for (executionProperty in executionSlo.properties!!) {
+                        benchmarkSlos[i].properties[executionProperty.key] = executionProperty.value
+                    }
+                }
+            }
+        }
+        return benchmarkSlos
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloJson.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloJson.kt
similarity index 78%
rename from theodolite/src/main/kotlin/theodolite/evaluation/SloJson.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloJson.kt
index 205389276f2c1adef6cba6c745baf99744c8d2dd..653ad6b5f998014a0f5b9e8b7397bcd3ce51f729 100644
--- a/theodolite/src/main/kotlin/theodolite/evaluation/SloJson.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloJson.kt
@@ -1,7 +1,7 @@
-package theodolite.evaluation
+package rocks.theodolite.kubernetes.slo
 
 import com.google.gson.Gson
-import theodolite.util.PromResult
+import rocks.theodolite.kubernetes.util.PromResult
 
 class SloJson constructor(
     val results: List<List<PromResult>>,
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloTypes.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloTypes.kt
similarity index 91%
rename from theodolite/src/main/kotlin/theodolite/evaluation/SloTypes.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloTypes.kt
index 812b50de779d2f3abfd5788b8aee145edc959e6c..07cbcd634ec7b46bd0e66a52f62989660575765f 100644
--- a/theodolite/src/main/kotlin/theodolite/evaluation/SloTypes.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloTypes.kt
@@ -1,4 +1,4 @@
-package theodolite.evaluation
+package rocks.theodolite.kubernetes.slo
 
 enum class SloTypes(val value: String) {
     GENERIC("generic"),
diff --git a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/standalone/TheodoliteStandalone.kt
similarity index 73%
rename from theodolite/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/standalone/TheodoliteStandalone.kt
index 1bbf3e01f461a19dbe588aedd41be63b84c86162..8cf3959b95374183a989a0217d754aea7eab716a 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/standalone/TheodoliteStandalone.kt
@@ -1,14 +1,18 @@
-package theodolite.execution
+package rocks.theodolite.kubernetes.standalone
 
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import mu.KotlinLogging
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.benchmark.KubernetesBenchmark
-import theodolite.util.YamlParserFromFile
-import theodolite.util.EvaluationFailedException
-import theodolite.util.ExecutionFailedException
+import rocks.theodolite.kubernetes.model.BenchmarkExecution
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark
+import rocks.theodolite.kubernetes.TheodoliteExecutor
+import rocks.theodolite.kubernetes.util.YamlParserFromFile
+import rocks.theodolite.kubernetes.slo.EvaluationFailedException
+import rocks.theodolite.kubernetes.ExecutionFailedException
+import rocks.theodolite.kubernetes.Shutdown
 import kotlin.concurrent.thread
 import kotlin.system.exitProcess
 
+
 private val logger = KotlinLogging.logger {}
 
 
@@ -27,7 +31,7 @@ private val logger = KotlinLogging.logger {}
  *
  * @constructor Create empty Theodolite yaml executor
  */
-class TheodoliteStandalone {
+class TheodoliteStandalone (private val client: NamespacedKubernetesClient) {
     private val parser = YamlParserFromFile()
 
     fun start() {
@@ -48,11 +52,11 @@ class TheodoliteStandalone {
 
         // Add shutdown hook
         // Use thread{} with start = false, else the thread will start right away
-        val shutdown = thread(start = false) { Shutdown(benchmarkExecution, benchmark).run() }
+        val shutdown = thread(start = false) { Shutdown(benchmarkExecution, benchmark, client).run() }
         Runtime.getRuntime().addShutdownHook(shutdown)
 
         try {
-            TheodoliteExecutor(benchmarkExecution, benchmark).run()
+            TheodoliteExecutor(benchmarkExecution, benchmark, client).setupAndRunExecution()
         } catch (e: EvaluationFailedException) {
             logger.error { "Evaluation failed with error: ${e.message}" }
         }catch (e: ExecutionFailedException) {
diff --git a/theodolite/src/main/kotlin/theodolite/util/ConfigurationOverride.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/ConfigurationOverride.kt
similarity index 81%
rename from theodolite/src/main/kotlin/theodolite/util/ConfigurationOverride.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/ConfigurationOverride.kt
index 537b44721bb344c2cd7af71d29dc4fa3da5a7a33..4b054d61c15c13b2058fd4848dd69fc4633610c8 100644
--- a/theodolite/src/main/kotlin/theodolite/util/ConfigurationOverride.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/ConfigurationOverride.kt
@@ -1,7 +1,8 @@
-package theodolite.util
+package rocks.theodolite.kubernetes.util
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.quarkus.runtime.annotations.RegisterForReflection
+import rocks.theodolite.kubernetes.patcher.PatcherDefinition
 
 /**
  * Representation of a configuration override.
diff --git a/theodolite/src/main/kotlin/theodolite/util/Parser.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/Parser.kt
similarity index 89%
rename from theodolite/src/main/kotlin/theodolite/util/Parser.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/Parser.kt
index e435b1cbbf18b9f860ceda69f5f7ec66e64c9375..65cd6a39303d3f0f0814c7197bbe15b4919be5d7 100644
--- a/theodolite/src/main/kotlin/theodolite/util/Parser.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/Parser.kt
@@ -1,4 +1,4 @@
-package theodolite.util
+package rocks.theodolite.kubernetes.util
 
 /**
  * Interface for parsers.
diff --git a/theodolite/src/main/kotlin/theodolite/util/YamlParserFromFile.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/YamlParserFromFile.kt
similarity index 83%
rename from theodolite/src/main/kotlin/theodolite/util/YamlParserFromFile.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/YamlParserFromFile.kt
index ae36349e628621bb7ad287d8cf557fbefa3ff5c5..f6a1179a880631dea7471b68b34c0823400aaadc 100644
--- a/theodolite/src/main/kotlin/theodolite/util/YamlParserFromFile.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/YamlParserFromFile.kt
@@ -1,4 +1,4 @@
-package theodolite.util
+package rocks.theodolite.kubernetes.util
 
 import org.yaml.snakeyaml.Yaml
 import org.yaml.snakeyaml.constructor.Constructor
@@ -9,6 +9,7 @@ import java.io.InputStream
 /**
  * The YamlParser parses a YAML file
  */
+@Deprecated("Use Jackson ObjectMapper instead")
 class YamlParserFromFile : Parser {
     override fun <T> parse(path: String, E: Class<T>): T? {
         val input: InputStream = FileInputStream(File(path))
diff --git a/theodolite/src/main/kotlin/theodolite/util/YamlParserFromString.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/YamlParserFromString.kt
similarity index 78%
rename from theodolite/src/main/kotlin/theodolite/util/YamlParserFromString.kt
rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/YamlParserFromString.kt
index 0e197908a501c0f6b89761a61989580b18e21f64..288414422963ad3de8f6b853b949b4af7939bf6a 100644
--- a/theodolite/src/main/kotlin/theodolite/util/YamlParserFromString.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/YamlParserFromString.kt
@@ -1,4 +1,4 @@
-package theodolite.util
+package rocks.theodolite.kubernetes.util
 
 import org.yaml.snakeyaml.Yaml
 import org.yaml.snakeyaml.constructor.Constructor
@@ -6,6 +6,7 @@ import org.yaml.snakeyaml.constructor.Constructor
 /**
  * The YamlParser parses a YAML string
  */
+@Deprecated("Use Jackson ObjectMapper instead")
 class YamlParserFromString : Parser {
     override fun <T> parse(fileString: String, E: Class<T>): T? {
         val parser = Yaml(Constructor(E))
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/Benchmark.kt b/theodolite/src/main/kotlin/theodolite/benchmark/Benchmark.kt
deleted file mode 100644
index cf2fac7337d79c1c5daf2b0fac070200cf27f9a5..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/benchmark/Benchmark.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package theodolite.benchmark
-
-import io.quarkus.runtime.annotations.RegisterForReflection
-import theodolite.util.ConfigurationOverride
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-
-/**
- * A Benchmark contains:
- * - The [Resource]s that can be scaled for the benchmark.
- * - The [LoadDimension]s that can be scaled the benchmark.
- * - additional [ConfigurationOverride]s.
- */
-@RegisterForReflection
-interface Benchmark {
-
-    fun setupInfrastructure()
-    fun teardownInfrastructure()
-
-    /**
-     * Builds a Deployment that can be deployed.
-     * @return a BenchmarkDeployment.
-     */
-    fun buildDeployment(
-        load: LoadDimension,
-        res: Resource,
-        configurationOverrides: List<ConfigurationOverride?>,
-        loadGenerationDelay: Long,
-        afterTeardownDelay: Long
-    ): BenchmarkDeployment
-}
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/FileSystemResourceSet.kt b/theodolite/src/main/kotlin/theodolite/benchmark/FileSystemResourceSet.kt
deleted file mode 100644
index f830232de4b6956fa0f989cae131903377862e6c..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/benchmark/FileSystemResourceSet.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-package theodolite.benchmark
-
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.client.NamespacedKubernetesClient
-import io.quarkus.runtime.annotations.RegisterForReflection
-import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
-import theodolite.util.DeploymentFailedException
-import theodolite.util.YamlParserFromFile
-import java.io.File
-import java.io.FileNotFoundException
-import java.lang.IllegalArgumentException
-
-@RegisterForReflection
-@JsonDeserialize
-class FileSystemResourceSet: ResourceSet, KubernetesResource {
-    lateinit var path: String
-    lateinit var files: List<String>
-
-    override fun getResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, KubernetesResource>> {
-
-        //if files is set ...
-        if(::files.isInitialized){
-            return files
-                    .map { loadSingleResource(resourceURL = it, client = client) }
-        }
-
-        return try {
-            File(path)
-                .list() !!
-                .filter { it.endsWith(".yaml") || it.endsWith(".yml") }
-                .map {
-                    loadSingleResource(resourceURL = it, client = client)
-                }
-        } catch (e: NullPointerException) {
-            throw  DeploymentFailedException("Could not load files located in $path", e)
-        }
-    }
-
-    private fun loadSingleResource(resourceURL: String, client: NamespacedKubernetesClient): Pair<String, KubernetesResource> {
-        val parser = YamlParserFromFile()
-        val loader = K8sResourceLoaderFromFile(client)
-        val resourcePath = "$path/$resourceURL"
-        lateinit var kind: String
-
-        try {
-            kind = parser.parse(resourcePath, HashMap<String, String>()::class.java)?.get("kind")!!
-        } catch (e: NullPointerException) {
-            throw DeploymentFailedException("Can not get Kind from resource $resourcePath", e)
-        } catch (e: FileNotFoundException){
-            throw DeploymentFailedException("File $resourcePath not found", e)
-
-        }
-
-        return try {
-            val k8sResource = loader.loadK8sResource(kind, resourcePath)
-            Pair(resourceURL, k8sResource)
-        } catch (e: IllegalArgumentException) {
-            throw DeploymentFailedException("Could not load resource: $resourcePath", e)
-        }
-    }
-}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt
deleted file mode 100644
index d42c2ea3c0ed5394fdcf5b89be0fe0470a15ba62..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt
+++ /dev/null
@@ -1,139 +0,0 @@
-package theodolite.benchmark
-
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.client.DefaultKubernetesClient
-import io.fabric8.kubernetes.client.NamespacedKubernetesClient
-import io.quarkus.runtime.annotations.RegisterForReflection
-import mu.KotlinLogging
-import theodolite.k8s.K8sManager
-import theodolite.k8s.resourceLoader.K8sResourceLoader
-import theodolite.patcher.PatcherFactory
-import theodolite.util.*
-
-
-private val logger = KotlinLogging.logger {}
-
-private var DEFAULT_NAMESPACE = "default"
-private var DEFAULT_THEODOLITE_APP_RESOURCES = "./benchmark-resources"
-
-/**
- * Represents a benchmark in Kubernetes. An example for this is the BenchmarkType.yaml
- * Contains a of:
- * - [name] of the benchmark,
- * - [appResource] list of the resources that have to be deployed for the benchmark,
- * - [loadGenResource] resource that generates the load,
- * - [resourceTypes] types of scaling resources,
- * - [loadTypes] types of loads that can be scaled for the benchmark,
- * - [kafkaConfig] for the [theodolite.k8s.TopicManager],
- * - [namespace] for the client,
- * - [path] under which the resource yamls can be found.
- *
- *  This class is used for the parsing(in the [theodolite.execution.TheodoliteStandalone]) and
- *  for the deserializing in the [theodolite.execution.operator.TheodoliteOperator].
- * @constructor construct an empty Benchmark.
- */
-@JsonDeserialize
-@RegisterForReflection
-class KubernetesBenchmark : KubernetesResource, Benchmark {
-    lateinit var name: String
-    lateinit var resourceTypes: List<TypeName>
-    lateinit var loadTypes: List<TypeName>
-    var kafkaConfig: KafkaConfig? = null
-    lateinit var infrastructure: Resources
-    lateinit var sut: Resources
-    lateinit var loadGenerator: Resources
-    private var namespace = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE
-
-    @Transient
-    private var client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(namespace)
-
-    /**
-     * Loads [KubernetesResource]s.
-     * It first loads them via the [YamlParserFromFile] to check for their concrete type and afterwards initializes them using
-     * the [K8sResourceLoader]
-     */
-    fun loadKubernetesResources(resourceSet: List<ResourceSets>): Collection<Pair<String, KubernetesResource>> {
-        return resourceSet.flatMap { it.loadResourceSet(this.client) }
-    }
-
-    override fun setupInfrastructure() {
-        this.infrastructure.beforeActions.forEach { it.exec(client = client) }
-        val kubernetesManager = K8sManager(this.client)
-        loadKubernetesResources(this.infrastructure.resources)
-            .map{it.second}
-            .forEach { kubernetesManager.deploy(it) }
-    }
-
-    override fun teardownInfrastructure() {
-        val kubernetesManager = K8sManager(this.client)
-        loadKubernetesResources(this.infrastructure.resources)
-            .map{it.second}
-            .forEach { kubernetesManager.remove(it) }
-        this.infrastructure.afterActions.forEach { it.exec(client = client) }
-    }
-
-    /**
-     * Builds a deployment.
-     * First loads all required resources and then patches them to the concrete load and resources for the experiment.
-     * Afterwards patches additional configurations(cluster depending) into the resources.
-     * @param load concrete load that will be benchmarked in this experiment.
-     * @param res concrete resource that will be scaled for this experiment.
-     * @param configurationOverrides
-     * @return a [BenchmarkDeployment]
-     */
-    override fun buildDeployment(
-        load: LoadDimension,
-        res: Resource,
-        configurationOverrides: List<ConfigurationOverride?>,
-        loadGenerationDelay: Long,
-        afterTeardownDelay: Long
-    ): BenchmarkDeployment {
-        logger.info { "Using $namespace as namespace." }
-
-        val appResources = loadKubernetesResources(this.sut.resources)
-        val loadGenResources = loadKubernetesResources(this.loadGenerator.resources)
-
-        val patcherFactory = PatcherFactory()
-
-        // patch the load dimension the resources
-        load.getType().forEach { patcherDefinition ->
-            patcherFactory.createPatcher(patcherDefinition, loadGenResources).patch(load.get().toString())
-        }
-        res.getType().forEach { patcherDefinition ->
-            patcherFactory.createPatcher(patcherDefinition, appResources).patch(res.get().toString())
-        }
-
-        // Patch the given overrides
-        configurationOverrides.forEach { override ->
-            override?.let {
-                patcherFactory.createPatcher(it.patcher, appResources + loadGenResources).patch(override.value)
-            }
-        }
-
-        val kafkaConfig = this.kafkaConfig
-
-        return KubernetesBenchmarkDeployment(
-            sutBeforeActions = sut.beforeActions,
-            sutAfterActions = sut.afterActions,
-            loadGenBeforeActions = loadGenerator.beforeActions,
-            loadGenAfterActions = loadGenerator.afterActions,
-            appResources = appResources.map { it.second },
-            loadGenResources = loadGenResources.map { it.second },
-            loadGenerationDelay = loadGenerationDelay,
-            afterTeardownDelay = afterTeardownDelay,
-            kafkaConfig = if (kafkaConfig != null) hashMapOf("bootstrap.servers" to kafkaConfig.bootstrapServer) else mapOf(),
-            topics = kafkaConfig?.topics ?: listOf(),
-            client = this.client
-        )
-    }
-
-    /**
-     * This function can be used to set the Kubernetes client manually. This is for example necessary for testing.
-     *
-     * @param client
-     */
-    fun setClient(client: NamespacedKubernetesClient) {
-        this.client = client
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/Resources.kt b/theodolite/src/main/kotlin/theodolite/benchmark/Resources.kt
deleted file mode 100644
index fccbd2c41a646a2ef85ef77c65763e7f793d1e91..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/benchmark/Resources.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package theodolite.benchmark
-
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize
-import io.quarkus.runtime.annotations.RegisterForReflection
-
-@JsonDeserialize
-@RegisterForReflection
-class Resources {
-
-    lateinit var resources: List<ResourceSets>
-    lateinit var beforeActions: List<Action>
-    lateinit var afterActions: List<Action>
-
-}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloConfigHandler.kt b/theodolite/src/main/kotlin/theodolite/evaluation/SloConfigHandler.kt
deleted file mode 100644
index 425a4f3b0634d53f8b1d5c4b8abdba9ca81c3f2b..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/evaluation/SloConfigHandler.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package theodolite.evaluation
-
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.util.InvalidPatcherConfigurationException
-import javax.enterprise.context.ApplicationScoped
-
-private const val CONSUMER_LAG_QUERY = "sum by(group)(kafka_consumergroup_group_lag >= 0)"
-private const val DROPPED_RECORDS_QUERY = "sum by(job) (kafka_streams_stream_task_metrics_dropped_records_total>=0)"
-
-@ApplicationScoped
-class SloConfigHandler {
-    companion object {
-        fun getQueryString(slo: BenchmarkExecution.Slo): String {
-            return when (slo.sloType.toLowerCase()) {
-                SloTypes.GENERIC.value -> slo.properties["promQLQuery"] ?: throw IllegalArgumentException("promQLQuery expected")
-                SloTypes.LAG_TREND.value, SloTypes.LAG_TREND_RATIO.value -> CONSUMER_LAG_QUERY
-                SloTypes.DROPPED_RECORDS.value, SloTypes.DROPPED_RECORDS_RATIO.value -> DROPPED_RECORDS_QUERY
-                else -> throw  InvalidPatcherConfigurationException("Could not find Prometheus query string for slo type $slo.sloType")
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt
deleted file mode 100644
index 3238f447be06ce6486bb7f6ca1758700f36ba558..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-package theodolite.execution
-
-import mu.KotlinLogging
-import theodolite.benchmark.Benchmark
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.util.ConfigurationOverride
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-import theodolite.util.Results
-import java.time.Duration
-import java.util.concurrent.atomic.AtomicBoolean
-
-private val logger = KotlinLogging.logger {}
-
-/**
- * The Benchmark Executor runs a single experiment.
- *
- * @property benchmark
- * @property results
- * @property executionDuration
- * @constructor Create empty Benchmark executor
- */
-abstract class BenchmarkExecutor(
-    val benchmark: Benchmark,
-    val results: Results,
-    val executionDuration: Duration,
-    val configurationOverrides: List<ConfigurationOverride?>,
-    val slos: List<BenchmarkExecution.Slo>,
-    val repetitions: Int,
-    val executionId: Int,
-    val loadGenerationDelay: Long,
-    val afterTeardownDelay: Long,
-    val executionName: String
-) {
-
-    var run: AtomicBoolean = AtomicBoolean(true)
-
-    /**
-     * Run a experiment for the given parametrization, evaluate the
-     * experiment and save the result.
-     *
-     * @param load load to be tested.
-     * @param res resources to be tested.
-     * @return True, if the number of resources are suitable for the
-     *     given load, false otherwise.
-     */
-    abstract fun runExperiment(load: LoadDimension, res: Resource): Boolean
-
-    /**
-     * Wait while the benchmark is running and log the number of minutes executed every 1 minute.
-     *
-     */
-    fun waitAndLog() {
-        logger.info { "Execution of a new experiment started." }
-
-        var secondsRunning = 0L
-
-        while (run.get() && secondsRunning < executionDuration.toSeconds()) {
-            secondsRunning++
-            Thread.sleep(Duration.ofSeconds(1).toMillis())
-
-            if ((secondsRunning % 60) == 0L) {
-                logger.info { "Executed: ${secondsRunning / 60} minutes." }
-            }
-        }
-
-        logger.debug { "Executor shutdown gracefully." }
-
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
deleted file mode 100644
index 8596576e0a7984c32b6dabf90c6bbf06961d2bb1..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
+++ /dev/null
@@ -1,164 +0,0 @@
-package theodolite.execution
-
-import mu.KotlinLogging
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.benchmark.KubernetesBenchmark
-import theodolite.patcher.PatcherDefinitionFactory
-import theodolite.strategies.StrategyFactory
-import theodolite.strategies.searchstrategy.CompositeStrategy
-import theodolite.util.*
-import java.io.File
-import java.time.Duration
-
-
-private val logger = KotlinLogging.logger {}
-
-/**
- * The Theodolite executor runs all the experiments defined with the given execution and benchmark configuration.
- *
- * @property config Configuration of a execution
- * @property kubernetesBenchmark Configuration of a benchmark
- * @constructor Create empty Theodolite executor
- */
-class TheodoliteExecutor(
-    private val config: BenchmarkExecution,
-    private val kubernetesBenchmark: KubernetesBenchmark
-) {
-    /**
-     * An executor object, configured with the specified benchmark, evaluation method, experiment duration
-     * and overrides which are given in the execution.
-     */
-    lateinit var executor: BenchmarkExecutor
-
-    /**
-     * Creates all required components to start Theodolite.
-     *
-     * @return a [Config], that contains a list of [LoadDimension]s,
-     *          a list of [Resource]s , and the [CompositeStrategy].
-     * The [CompositeStrategy] is configured and able to find the minimum required resource for the given load.
-     */
-    private fun buildConfig(): Config {
-        val results = Results()
-        val strategyFactory = StrategyFactory()
-
-        val executionDuration = Duration.ofSeconds(config.execution.duration)
-
-        val resourcePatcherDefinition =
-            PatcherDefinitionFactory().createPatcherDefinition(
-                config.resources.resourceType,
-                this.kubernetesBenchmark.resourceTypes
-            )
-
-        val loadDimensionPatcherDefinition =
-            PatcherDefinitionFactory().createPatcherDefinition(
-                config.load.loadType,
-                this.kubernetesBenchmark.loadTypes
-            )
-
-        executor =
-            BenchmarkExecutorImpl(
-                benchmark = kubernetesBenchmark,
-                results = results,
-                executionDuration = executionDuration,
-                configurationOverrides = config.configOverrides,
-                slos = config.slos,
-                repetitions = config.execution.repetitions,
-                executionId = config.executionId,
-                loadGenerationDelay = config.execution.loadGenerationDelay,
-                afterTeardownDelay = config.execution.afterTeardownDelay,
-                executionName = config.name
-            )
-
-        if (config.load.loadValues != config.load.loadValues.sorted()) {
-            config.load.loadValues = config.load.loadValues.sorted()
-            logger.info {
-                "Load values are not sorted correctly, Theodolite sorts them in ascending order." +
-                        "New order is: ${config.load.loadValues}"
-            }
-        }
-
-        if (config.resources.resourceValues != config.resources.resourceValues.sorted()) {
-            config.resources.resourceValues = config.resources.resourceValues.sorted()
-            logger.info {
-                "Load values are not sorted correctly, Theodolite sorts them in ascending order." +
-                        "New order is: ${config.resources.resourceValues}"
-            }
-        }
-
-        return Config(
-            loads = config.load.loadValues.map { load -> LoadDimension(load, loadDimensionPatcherDefinition) },
-            resources = config.resources.resourceValues.map { resource ->
-                Resource(
-                    resource,
-                    resourcePatcherDefinition
-                )
-            },
-            compositeStrategy = CompositeStrategy(
-                benchmarkExecutor = executor,
-                searchStrategy = strategyFactory.createSearchStrategy(executor, config.execution.strategy),
-                restrictionStrategies = strategyFactory.createRestrictionStrategy(
-                    results,
-                    config.execution.restrictions
-                )
-            )
-        )
-    }
-
-    fun getExecution(): BenchmarkExecution {
-        return this.config
-    }
-
-    /**
-     * Run all experiments which are specified in the corresponding
-     * execution and benchmark objects.
-     */
-    fun run() {
-        kubernetesBenchmark.setupInfrastructure()
-
-        val ioHandler = IOHandler()
-        val resultsFolder = ioHandler.getResultFolderURL()
-        this.config.executionId = getAndIncrementExecutionID(resultsFolder + "expID.txt")
-        ioHandler.writeToJSONFile(this.config, "${resultsFolder}exp${this.config.executionId}-execution-configuration")
-        ioHandler.writeToJSONFile(
-            kubernetesBenchmark,
-            "${resultsFolder}exp${this.config.executionId}-benchmark-configuration"
-        )
-
-        val config = buildConfig()
-        // execute benchmarks for each load
-        try {
-            for (load in config.loads) {
-                if (executor.run.get()) {
-                    config.compositeStrategy.findSuitableResource(load, config.resources)
-                }
-            }
-        } finally {
-            ioHandler.writeToJSONFile(
-                config.compositeStrategy.benchmarkExecutor.results,
-                "${resultsFolder}exp${this.config.executionId}-result"
-            )
-            // Create expXYZ_demand.csv file
-            ioHandler.writeToCSVFile(
-                "${resultsFolder}exp${this.config.executionId}_demand",
-                calculateDemandMetric(config.loads, config.compositeStrategy.benchmarkExecutor.results),
-                listOf("load","resources")
-            )
-        }
-        kubernetesBenchmark.teardownInfrastructure()
-    }
-
-    private fun getAndIncrementExecutionID(fileURL: String): Int {
-        val ioHandler = IOHandler()
-        var executionID = 0
-        if (File(fileURL).exists()) {
-            executionID = ioHandler.readFileAsString(fileURL).toInt() + 1
-        }
-        ioHandler.writeStringToTextFile(fileURL, (executionID).toString())
-        return executionID
-    }
-
-    private fun calculateDemandMetric(loadDimensions: List<LoadDimension>, results: Results): List<List<String>> {
-        return loadDimensions.map { listOf(it.get().toString(), results.getMinRequiredInstances(it).get().toString()) }
-    }
-
-}
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/CustomResourceWrapper.kt b/theodolite/src/main/kotlin/theodolite/k8s/CustomResourceWrapper.kt
deleted file mode 100644
index 797ed88389947d66aa626ba2ef3fdf6732f8369d..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/k8s/CustomResourceWrapper.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-package theodolite.k8s
-
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.client.NamespacedKubernetesClient
-import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
-import mu.KotlinLogging
-
-private val logger = KotlinLogging.logger {}
-
-class CustomResourceWrapper(
-    val crAsMap: Map<String, String>,
-    private val context: CustomResourceDefinitionContext
-) : KubernetesResource {
-    /**
-     * Deploy a service monitor
-     *
-     * @param client a namespaced Kubernetes client which are used to deploy the CR object.
-     *
-     * @throws java.io.IOException if the resource could not be deployed.
-     */
-    fun deploy(client: NamespacedKubernetesClient) {
-        client.customResource(this.context)
-            .createOrReplace(client.configuration.namespace, this.crAsMap as Map<String, Any>)
-    }
-
-    /**
-     * Delete a service monitor
-     *
-     * @param client a namespaced Kubernetes client which are used to delete the CR object.
-     */
-    fun delete(client: NamespacedKubernetesClient) {
-        try {
-            client.customResource(this.context)
-                .delete(client.configuration.namespace, this.getName())
-        } catch (e: Exception) {
-            logger.warn { "Could not delete custom resource" }
-        }
-    }
-
-    /**
-     * @throws NullPointerException if name or metadata is null
-     */
-    fun getName(): String {
-        val metadataAsMap = this.crAsMap["metadata"]!! as Map<String, String>
-        return metadataAsMap["name"]!!
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/AbstractK8sLoader.kt b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/AbstractK8sLoader.kt
deleted file mode 100644
index 871b8cf43907fcb8b0b5ea501c6b47f82e56ff69..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/AbstractK8sLoader.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-package theodolite.k8s.resourceLoader
-
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import mu.KotlinLogging
-import theodolite.k8s.K8sContextFactory
-
-private val logger = KotlinLogging.logger {}
-
-abstract class AbstractK8sLoader: K8sResourceLoader {
-
-    fun loadK8sResource(kind: String, resourceString: String): KubernetesResource {
-        return when (kind.replaceFirst(kind[0],kind[0].uppercaseChar())) {
-            "Deployment" -> loadDeployment(resourceString)
-            "Service" -> loadService(resourceString)
-            "ServiceMonitor" -> loadServiceMonitor(resourceString)
-            "ConfigMap" -> loadConfigmap(resourceString)
-            "StatefulSet" -> loadStatefulSet(resourceString)
-            "Execution" -> loadExecution(resourceString)
-            "Benchmark" -> loadBenchmark(resourceString)
-            else -> {
-                logger.error { "Error during loading of unspecified resource Kind '$kind'." }
-                throw IllegalArgumentException("error while loading resource with kind: $kind")
-            }
-        }
-    }
-
-    fun <T : KubernetesResource> loadGenericResource(resourceString: String, f: (String) -> T): T {
-        var resource: T? = null
-
-        try {
-            resource = f(resourceString)
-        } catch (e: Exception) {
-            logger.warn { e }
-        }
-
-        if (resource == null) {
-            throw IllegalArgumentException("The Resource: $resourceString could not be loaded")
-        }
-        return resource
-    }
-
-
-
-    override fun loadServiceMonitor(resource: String): KubernetesResource {
-        val context = K8sContextFactory().create(
-            api = "v1",
-            scope = "Namespaced",
-            group = "monitoring.coreos.com",
-            plural = "servicemonitors"
-        )
-        return loadCustomResourceWrapper(resource, context)
-    }
-
-    override fun loadExecution(resource: String): KubernetesResource {
-        val context = K8sContextFactory().create(
-            api = "v1",
-            scope = "Namespaced",
-            group = "theodolite.com",
-            plural = "executions"
-        )
-        return loadCustomResourceWrapper(resource, context)
-    }
-
-    override fun loadBenchmark(resource: String): KubernetesResource {
-        val context = K8sContextFactory().create(
-            api = "v1",
-            scope = "Namespaced",
-            group = "theodolite.com",
-            plural = "benchmarks"
-        )
-        return loadCustomResourceWrapper(resource, context)
-    }
-}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoader.kt b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoader.kt
deleted file mode 100644
index c123ab2958132cb43ad188136f738b561e91310b..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoader.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package theodolite.k8s.resourceLoader
-
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
-
-interface K8sResourceLoader {
-    fun loadDeployment(resource: String): KubernetesResource
-    fun loadService(resource: String): KubernetesResource
-    fun loadStatefulSet(resource: String): KubernetesResource
-    fun loadExecution(resource: String): KubernetesResource
-    fun loadBenchmark(resource: String): KubernetesResource
-    fun loadConfigmap(resource: String): KubernetesResource
-    fun loadServiceMonitor(resource: String): KubernetesResource
-    fun loadCustomResourceWrapper(resource: String, context: CustomResourceDefinitionContext): KubernetesResource
-}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromFile.kt b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromFile.kt
deleted file mode 100644
index 08f34e1d67c9821c9f9a07a49f4ba8683a072611..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromFile.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-package theodolite.k8s.resourceLoader
-
-import io.fabric8.kubernetes.api.model.ConfigMap
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.api.model.Service
-import io.fabric8.kubernetes.api.model.apps.Deployment
-import io.fabric8.kubernetes.client.NamespacedKubernetesClient
-import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
-import theodolite.k8s.CustomResourceWrapper
-import theodolite.util.YamlParserFromFile
-
-/**
- * Used to load different Kubernetes resources.
- * Supports: Deployments, Services, ConfigMaps, and CustomResources.
- * @param client KubernetesClient used to deploy or remove.
- */
-class K8sResourceLoaderFromFile(private val client: NamespacedKubernetesClient): AbstractK8sLoader(),
-    K8sResourceLoader {
-
-    /**
-     * Parses a Service from a service yaml
-     * @param resource of the yaml file
-     * @return Service from fabric8
-     */
-    override fun loadService(resource: String): Service {
-        return loadGenericResource(resource) { x: String -> client.services().load(x).get() }
-    }
-
-
-    /**
-     * Parses a CustomResource from a yaml
-     * @param path of the yaml file
-     * @param context specific crd context for this custom resource
-     * @return  CustomResourceWrapper from fabric8
-     */
-    override fun loadCustomResourceWrapper(resource: String, context: CustomResourceDefinitionContext): CustomResourceWrapper {
-       return loadGenericResource(resource) {
-           CustomResourceWrapper(
-               YamlParserFromFile().parse(
-                   resource,
-                   HashMap<String, String>()::class.java
-               )!!,
-               context
-           )
-       }
-   }
-
-    /**
-     * Parses a Deployment from a Deployment yaml
-     * @param resource of the yaml file
-     * @return Deployment from fabric8
-     */
-    override fun loadDeployment(resource: String): Deployment {
-        return loadGenericResource(resource) { x: String -> client.apps().deployments().load(x).get() }
-    }
-
-    /**
-     * Parses a ConfigMap from a ConfigMap yaml
-     * @param resource of the yaml file
-     * @return ConfigMap from fabric8
-     */
-    override fun loadConfigmap(resource: String): ConfigMap {
-        return loadGenericResource(resource) { x: String -> client.configMaps().load(x).get() }
-    }
-
-    /**
-     * Parses a StatefulSet from a StatefulSet yaml
-     * @param resource of the yaml file
-     * @return StatefulSet from fabric8
-     */
-    override fun loadStatefulSet(resource: String): KubernetesResource {
-        return loadGenericResource(resource) { x: String -> client.apps().statefulSets().load(x).get() }
-
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromString.kt b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromString.kt
deleted file mode 100644
index 639e4c4584d47968cd718d601f1cd7064d85eda2..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromString.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-package theodolite.k8s.resourceLoader
-
-import io.fabric8.kubernetes.api.model.ConfigMap
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.api.model.Service
-import io.fabric8.kubernetes.api.model.apps.Deployment
-import io.fabric8.kubernetes.api.model.apps.StatefulSet
-import io.fabric8.kubernetes.client.NamespacedKubernetesClient
-import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
-import theodolite.k8s.CustomResourceWrapper
-import theodolite.util.YamlParserFromString
-import java.io.ByteArrayInputStream
-import java.io.InputStream
-
-class K8sResourceLoaderFromString(private val client: NamespacedKubernetesClient): AbstractK8sLoader(),
-    K8sResourceLoader {
-
-    override fun loadService(resource: String): Service {
-        return loadAnyResource(resource) { stream -> client.services().load(stream).get() }
-    }
-
-    override fun loadDeployment(resource: String): Deployment {
-        return loadAnyResource(resource) { stream -> client.apps().deployments().load(stream).get() }
-    }
-
-    override fun loadConfigmap(resource: String): ConfigMap {
-        return loadAnyResource(resource) { stream -> client.configMaps().load(stream).get() }
-    }
-
-    override fun loadStatefulSet(resource: String): StatefulSet {
-        return loadAnyResource(resource) { stream -> client.apps().statefulSets().load(stream).get() }
-    }
-
-    private fun <T : KubernetesResource> loadAnyResource(resource: String, f: (InputStream) -> T): T {
-        return loadGenericResource(resource) { f(ByteArrayInputStream(it.encodeToByteArray())) }
-    }
-
-    /**
-     * Parses a CustomResource from a yaml
-     * @param resource of the yaml file
-     * @param context specific crd context for this custom resource
-     * @return  CustomResourceWrapper from fabric8
-     */
-    override fun loadCustomResourceWrapper(resource: String, context: CustomResourceDefinitionContext): CustomResourceWrapper {
-        return loadGenericResource(resource) {
-            CustomResourceWrapper(
-                YamlParserFromString().parse(
-                    resource,
-                    HashMap<String, String>()::class.java
-                )!!,
-                context
-            )
-        }
-    }
-}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/AbstractPatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/AbstractPatcher.kt
deleted file mode 100644
index df80e9cbd2503685a7dbed35db5319920dfc42cb..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/patcher/AbstractPatcher.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package theodolite.patcher
-
-import io.fabric8.kubernetes.api.model.KubernetesResource
-
-/**
- * A Patcher is able to modify values of a Kubernetes resource, see [Patcher].
- *
- * An AbstractPatcher is created with up to three parameters.
- *
- * @param k8sResource The Kubernetes resource to be patched.
- * @param container *(optional)* The name of the container to be patched
- * @param variableName *(optional)* The variable name to be patched
- *
- *
- * **For example** to patch the load dimension of a load generator, the patcher should be created as follow:
- *
- * k8sResource: `uc-1-workload-generator.yaml`
- * container: `workload`
- * variableName: `NUM_SENSORS`
- *
- */
-abstract class AbstractPatcher(
-    k8sResource: KubernetesResource
-) : Patcher
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/ImagePatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/ImagePatcher.kt
deleted file mode 100644
index 8f6753372076c119324dc962112928253633b6b0..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/patcher/ImagePatcher.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package theodolite.patcher
-
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.api.model.apps.Deployment
-import io.fabric8.kubernetes.api.model.apps.StatefulSet
-
-/**
- * The Image patcher allows to change the image of a container.
- *
- * @param k8sResource Kubernetes resource to be patched.
- * @param container Container to be patched.
- */
-class ImagePatcher(private val k8sResource: KubernetesResource, private val container: String) :
-    AbstractPatcher(k8sResource) {
-
-    override fun <String> patch(imagePath: String) {
-        if (k8sResource is Deployment) {
-            k8sResource.spec.template.spec.containers.filter { it.name == container }.forEach {
-                it.image = imagePath as kotlin.String
-            }
-        } else if (k8sResource is StatefulSet) {
-            k8sResource.spec.template.spec.containers.filter { it.name == container }.forEach {
-                it.image = imagePath as kotlin.String
-            }
-        }
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/LabelPatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/LabelPatcher.kt
deleted file mode 100644
index 2f8c703afa9e826a79f0785abef493d2d448ac74..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/patcher/LabelPatcher.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-package theodolite.patcher
-
-import io.fabric8.kubernetes.api.model.ConfigMap
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.api.model.Service
-import io.fabric8.kubernetes.api.model.apps.Deployment
-import io.fabric8.kubernetes.api.model.apps.StatefulSet
-import io.fabric8.kubernetes.client.CustomResource
-
-class LabelPatcher(private val k8sResource: KubernetesResource, val variableName: String) :
-    AbstractPatcher(k8sResource) {
-
-    override fun <String> patch(labelValue: String) {
-        if (labelValue is kotlin.String) {
-            when (k8sResource) {
-                is Deployment -> {
-                    if (k8sResource.metadata.labels == null) {
-                        k8sResource.metadata.labels = mutableMapOf()
-                    }
-                    k8sResource.metadata.labels[this.variableName] = labelValue
-                }
-                is StatefulSet -> {
-                    if (k8sResource.metadata.labels == null) {
-                        k8sResource.metadata.labels = mutableMapOf()
-                    }
-                    k8sResource.metadata.labels[this.variableName] = labelValue
-                }
-                is Service -> {
-                    if (k8sResource.metadata.labels == null) {
-                        k8sResource.metadata.labels = mutableMapOf()
-                    }
-                    k8sResource.metadata.labels[this.variableName] = labelValue
-                }
-                is ConfigMap -> {
-                    if (k8sResource.metadata.labels == null) {
-                        k8sResource.metadata.labels = mutableMapOf()
-                    }
-                    k8sResource.metadata.labels[this.variableName] = labelValue
-                }
-                is CustomResource<*, *> -> {
-                    if (k8sResource.metadata.labels == null) {
-                        k8sResource.metadata.labels = mutableMapOf()
-                    }
-                    k8sResource.metadata.labels[this.variableName] = labelValue
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/NodeSelectorPatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/NodeSelectorPatcher.kt
deleted file mode 100644
index 0e8cd553a6c6a9ed6fa2c8cc1b84e4cfebe79d73..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/patcher/NodeSelectorPatcher.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package theodolite.patcher
-
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.api.model.apps.Deployment
-
-/**
- * The Node selector patcher make it possible to set the NodeSelector of a Kubernetes deployment.
- *
- * @param k8sResource Kubernetes resource to be patched.
- * @param variableName The `label-key` of the node for which the `label-value` is to be patched.
- */
-class NodeSelectorPatcher(private val k8sResource: KubernetesResource, private val variableName: String) :
-    AbstractPatcher(k8sResource) {
-    override fun <String> patch(value: String) {
-        if (k8sResource is Deployment) {
-            k8sResource.spec.template.spec.nodeSelector = mapOf(variableName to value as kotlin.String)
-        }
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt
deleted file mode 100644
index c617917e6894c3a30779dd4257a96365ded35481..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package theodolite.patcher
-
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.api.model.apps.Deployment
-import kotlin.math.pow
-
-class NumNestedGroupsLoadGeneratorReplicaPatcher(
-    private val k8sResource: KubernetesResource,
-    private val numSensors: String,
-    private val loadGenMaxRecords: String
-) :
-    AbstractPatcher(k8sResource) {
-    override fun <String> patch(value: String) {
-        if (k8sResource is Deployment) {
-            if (value is kotlin.String) {
-                val approxNumSensors = numSensors.toDouble().pow(Integer.parseInt(value).toDouble())
-                val loadGenInstances =
-                    (approxNumSensors + loadGenMaxRecords.toDouble() - 1) / loadGenMaxRecords.toDouble()
-                this.k8sResource.spec.replicas = loadGenInstances.toInt()
-            }
-        }
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt
deleted file mode 100644
index 86bb37db3cb9fd0d3bca1690d5eb4e622329a9bc..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package theodolite.patcher
-
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.api.model.apps.Deployment
-
-
-class NumSensorsLoadGeneratorReplicaPatcher(
-    private val k8sResource: KubernetesResource,
-    private val loadGenMaxRecords: String
-) :
-    AbstractPatcher(k8sResource) {
-    override fun <String> patch(value: String) {
-        if (k8sResource is Deployment) {
-            if (value is kotlin.String) {
-                val loadGenInstances =
-                    (Integer.parseInt(value) + loadGenMaxRecords.toInt() - 1) / loadGenMaxRecords.toInt()
-                this.k8sResource.spec.replicas = loadGenInstances
-            }
-        }
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/PatcherFactory.kt b/theodolite/src/main/kotlin/theodolite/patcher/PatcherFactory.kt
deleted file mode 100644
index 88b3e19e999a889cdcb8345ca7c90c37a6e6d275..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/patcher/PatcherFactory.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-package theodolite.patcher
-
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import theodolite.util.InvalidPatcherConfigurationException
-import theodolite.util.PatcherDefinition
-
-/**
- * The Patcher factory creates [Patcher]s
- *
- * @constructor Creates an empty PatcherFactory.
- */
-class PatcherFactory {
-    /**
-     * Create patcher based on the given [PatcherDefinition] and
-     * the list of KubernetesResources.
-     *
-     * @param patcherDefinition The [PatcherDefinition] for which are
-     *     [Patcher] should be created.
-     * @param k8sResources List of all available Kubernetes resources.
-     *     This is a list of pairs<String, KubernetesResource>:
-     *     The frist corresponds to the filename where the resource is defined.
-     *     The second corresponds to the concrete [KubernetesResource] that should be patched.
-     * @return The created [Patcher].
-     * @throws IllegalArgumentException if no patcher can be created.
-     */
-    fun createPatcher(
-        patcherDefinition: PatcherDefinition,
-        k8sResources: Collection<Pair<String, KubernetesResource>>
-    ): Patcher {
-        val resource =
-            k8sResources.filter { it.first == patcherDefinition.resource }
-                .map { resource -> resource.second }
-                .firstOrNull()
-                ?: throw InvalidPatcherConfigurationException("Could not find resource ${patcherDefinition.resource}")
-
-        return try {
-            when (patcherDefinition.type) {
-                "ReplicaPatcher" -> ReplicaPatcher(
-                    k8sResource = resource
-                )
-                "NumNestedGroupsLoadGeneratorReplicaPatcher" -> NumNestedGroupsLoadGeneratorReplicaPatcher(
-                    k8sResource = resource,
-                    loadGenMaxRecords = patcherDefinition.properties["loadGenMaxRecords"]!!,
-                    numSensors = patcherDefinition.properties["numSensors"]!!
-                )
-                "NumSensorsLoadGeneratorReplicaPatcher" -> NumSensorsLoadGeneratorReplicaPatcher(
-                    k8sResource = resource,
-                    loadGenMaxRecords = patcherDefinition.properties["loadGenMaxRecords"]!!
-                )
-                "DataVolumeLoadGeneratorReplicaPatcher" -> DataVolumeLoadGeneratorReplicaPatcher(
-                    k8sResource = resource,
-                    maxVolume = patcherDefinition.properties["maxVolume"]!!.toInt(),
-                    container = patcherDefinition.properties["container"]!!,
-                    variableName = patcherDefinition.properties["variableName"]!!
-                )
-                "EnvVarPatcher" -> EnvVarPatcher(
-                    k8sResource = resource,
-                    container = patcherDefinition.properties["container"]!!,
-                    variableName = patcherDefinition.properties["variableName"]!!
-                )
-                "NodeSelectorPatcher" -> NodeSelectorPatcher(
-                    k8sResource = resource,
-                    variableName = patcherDefinition.properties["variableName"]!!
-                )
-                "ResourceLimitPatcher" -> ResourceLimitPatcher(
-                    k8sResource = resource,
-                    container = patcherDefinition.properties["container"]!!,
-                    limitedResource = patcherDefinition.properties["limitedResource"]!!
-                )
-                "ResourceRequestPatcher" -> ResourceRequestPatcher(
-                    k8sResource = resource,
-                    container = patcherDefinition.properties["container"]!!,
-                    requestedResource = patcherDefinition.properties["requestedResource"]!!
-                )
-                "SchedulerNamePatcher" -> SchedulerNamePatcher(
-                    k8sResource = resource
-                )
-                "LabelPatcher" -> LabelPatcher(
-                    k8sResource = resource,
-                    variableName = patcherDefinition.properties["variableName"]!!
-                )
-                "ImagePatcher" -> ImagePatcher(
-                    k8sResource = resource,
-                    container = patcherDefinition.properties["container"]!!
-                )
-                else -> throw InvalidPatcherConfigurationException("Patcher type ${patcherDefinition.type} not found.")
-            }
-        } catch (e: NullPointerException) {
-            throw InvalidPatcherConfigurationException(
-                "Could not create patcher with type ${patcherDefinition.type}" +
-                        " Probably a required patcher argument was not specified.", e
-            )
-        }
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/ReplicaPatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/ReplicaPatcher.kt
deleted file mode 100644
index 4cc35f2ed74f9e366c266c3f98f1b3d36d4ba1b8..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/patcher/ReplicaPatcher.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package theodolite.patcher
-
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.api.model.apps.Deployment
-
-/**
- * The Replica [Patcher] modifies the number of replicas for the given Kubernetes deployment.
- *
- * @param k8sResource  Kubernetes resource to be patched.
- */
-class ReplicaPatcher(private val k8sResource: KubernetesResource) : AbstractPatcher(k8sResource) {
-    override fun <String> patch(value: String) {
-        if (k8sResource is Deployment) {
-            if (value is kotlin.String) {
-                this.k8sResource.spec.replicas = Integer.parseInt(value)
-            }
-        }
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/SchedulerNamePatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/SchedulerNamePatcher.kt
deleted file mode 100644
index 348f0c50090a34c91221d3e099c3532375a578da..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/patcher/SchedulerNamePatcher.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package theodolite.patcher
-
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.api.model.apps.Deployment
-
-/**
- * The Scheduler name [Patcher] make it possible to set the scheduler which should
- * be used to deploy the given deployment.
- * @param k8sResource Kubernetes resource to be patched.
- */
-class SchedulerNamePatcher(private val k8sResource: KubernetesResource) : Patcher {
-    override fun <String> patch(value: String) {
-        if (k8sResource is Deployment) {
-            k8sResource.spec.template.spec.schedulerName = value as kotlin.String
-        }
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/StrategyFactory.kt b/theodolite/src/main/kotlin/theodolite/strategies/StrategyFactory.kt
deleted file mode 100644
index 829370e8ce1c181c1a4cb9fdd8ccf0ecefd48d3d..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/strategies/StrategyFactory.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-package theodolite.strategies
-
-import theodolite.execution.BenchmarkExecutor
-import theodolite.strategies.restriction.LowerBoundRestriction
-import theodolite.strategies.restriction.RestrictionStrategy
-import theodolite.strategies.searchstrategy.BinarySearch
-import theodolite.strategies.searchstrategy.FullSearch
-import theodolite.strategies.searchstrategy.LinearSearch
-import theodolite.strategies.searchstrategy.SearchStrategy
-import theodolite.util.Results
-
-/**
- * Factory for creating [SearchStrategy] and [RestrictionStrategy] strategies.
- */
-class StrategyFactory {
-
-    /**
-     * Create a [SearchStrategy].
-     *
-     * @param executor The [theodolite.execution.BenchmarkExecutor] that executes individual experiments.
-     * @param searchStrategyString Specifies the [SearchStrategy]. Must either be the string 'LinearSearch',
-     * or 'BinarySearch'.
-     *
-     * @throws IllegalArgumentException if the [SearchStrategy] was not one of the allowed options.
-     */
-    fun createSearchStrategy(executor: BenchmarkExecutor, searchStrategyString: String): SearchStrategy {
-        return when (searchStrategyString) {
-            "FullSearch" -> FullSearch(executor)
-            "LinearSearch" -> LinearSearch(executor)
-            "BinarySearch" -> BinarySearch(executor)
-            else -> throw IllegalArgumentException("Search Strategy $searchStrategyString not found")
-        }
-    }
-
-    /**
-     * Create a [RestrictionStrategy].
-     *
-     * @param results The [Results] saves the state of the Theodolite benchmark run.
-     * @param restrictionStrings Specifies the list of [RestrictionStrategy] that are used to restrict the amount
-     * of [theodolite.util.Resource] for a fixed LoadDimension. Must equal the string
-     * 'LowerBound'.
-     *
-     * @throws IllegalArgumentException if param searchStrategyString was not one of the allowed options.
-     */
-    fun createRestrictionStrategy(results: Results, restrictionStrings: List<String>): Set<RestrictionStrategy> {
-        return restrictionStrings
-            .map { restriction ->
-                when (restriction) {
-                    "LowerBound" -> LowerBoundRestriction(results)
-                    else -> throw IllegalArgumentException("Restriction Strategy $restrictionStrings not found")
-                }
-            }.toSet()
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/restriction/LowerBoundRestriction.kt b/theodolite/src/main/kotlin/theodolite/strategies/restriction/LowerBoundRestriction.kt
deleted file mode 100644
index 13bfedfe055f2bd428137f89b2986f3967ec797c..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/strategies/restriction/LowerBoundRestriction.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package theodolite.strategies.restriction
-
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-import theodolite.util.Results
-
-/**
- * The [LowerBoundRestriction] sets the lower bound of the resources to be examined to the value
- * needed to successfully execute the next smaller load.
- *
- * @param results [Result] object used as a basis to restrict the resources.
- */
-class LowerBoundRestriction(results: Results) : RestrictionStrategy(results) {
-
-    override fun apply(load: LoadDimension, resources: List<Resource>): List<Resource> {
-        val maxLoad: LoadDimension? = this.results.getMaxBenchmarkedLoad(load)
-        var lowerBound: Resource? = this.results.getMinRequiredInstances(maxLoad)
-        if (lowerBound == null) {
-            lowerBound = resources[0]
-        }
-        return resources.filter { x -> x.get() >= lowerBound.get() }
-    }
-
-}
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/restriction/RestrictionStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/restriction/RestrictionStrategy.kt
deleted file mode 100644
index 1ab7302d7898daad729b1c94c32d97138b5cdcf4..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/strategies/restriction/RestrictionStrategy.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package theodolite.strategies.restriction
-
-import io.quarkus.runtime.annotations.RegisterForReflection
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-import theodolite.util.Results
-
-/**
- * A 'Restriction Strategy' restricts a list of resources based on the current
- * results of all previously performed benchmarks.
- *
- * @param results the [Results] object
- */
-@RegisterForReflection
-abstract class RestrictionStrategy(val results: Results) {
-    /**
-     * Apply the restriction of the given resource list for the given load based on the results object.
-     *
-     * @param load [LoadDimension] for which a subset of resources are required.
-     * @param resources List of [Resource]s to be restricted.
-     * @return Returns a list containing only elements that have not been filtered out by the
-     * restriction (possibly empty).
-     */
-    abstract fun apply(load: LoadDimension, resources: List<Resource>): List<Resource>
-}
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/BinarySearch.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/BinarySearch.kt
deleted file mode 100644
index 28e8194c699cd074026c8cb7e6f3ce4ec347023b..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/BinarySearch.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-package theodolite.strategies.searchstrategy
-
-import mu.KotlinLogging
-import theodolite.execution.BenchmarkExecutor
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-
-private val logger = KotlinLogging.logger {}
-
-/**
- *  Binary-search-like implementation for determining the smallest suitable number of instances.
- *
- * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks.
- */
-class BinarySearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmarkExecutor) {
-    override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? {
-        val result = binarySearch(load, resources, 0, resources.size - 1)
-        if (result == -1) {
-            return null
-        }
-        return resources[result]
-    }
-
-    /**
-     * Apply binary search.
-     *
-     * @param load the load dimension to perform experiments for
-     * @param resources the list in which binary search is performed
-     * @param lower lower bound for binary search (inclusive)
-     * @param upper upper bound for binary search (inclusive)
-     */
-    private fun binarySearch(load: LoadDimension, resources: List<Resource>, lower: Int, upper: Int): Int {
-        if (lower > upper) {
-            throw IllegalArgumentException()
-        }
-        // special case:  length == 1 or 2
-        if (lower == upper) {
-            val res = resources[lower]
-            logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" }
-            if (this.benchmarkExecutor.runExperiment(load, resources[lower])) return lower
-            else {
-                if (lower + 1 == resources.size) return -1
-                return lower + 1
-            }
-        } else {
-            // apply binary search for a list with
-            // length > 2 and adjust upper and lower depending on the result for `resources[mid]`
-            val mid = (upper + lower) / 2
-            val res = resources[mid]
-            logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" }
-            if (this.benchmarkExecutor.runExperiment(load, resources[mid])) {
-                if (mid == lower) {
-                    return lower
-                }
-                return binarySearch(load, resources, lower, mid - 1)
-            } else {
-                return binarySearch(load, resources, mid + 1, upper)
-            }
-        }
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/CompositeStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/CompositeStrategy.kt
deleted file mode 100644
index d6ace6f564239e73a0d59f8eb7900f50018482c5..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/CompositeStrategy.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-package theodolite.strategies.searchstrategy
-
-import io.quarkus.runtime.annotations.RegisterForReflection
-import theodolite.execution.BenchmarkExecutor
-import theodolite.strategies.restriction.RestrictionStrategy
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-
-/**
- *  Composite strategy that combines a SearchStrategy and a set of RestrictionStrategy.
- *
- * @param searchStrategy the [SearchStrategy] that is executed as part of this [CompositeStrategy].
- * @param restrictionStrategies the set of [RestrictionStrategy] that are connected conjunctive to restrict the [Resource]
- * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks.
- */
-@RegisterForReflection
-class CompositeStrategy(
-    benchmarkExecutor: BenchmarkExecutor,
-    private val searchStrategy: SearchStrategy,
-    val restrictionStrategies: Set<RestrictionStrategy>
-) : SearchStrategy(benchmarkExecutor) {
-
-    override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? {
-        var restrictedResources = resources.toList()
-        for (strategy in this.restrictionStrategies) {
-            restrictedResources = restrictedResources.intersect(strategy.apply(load, resources).toSet()).toList()
-        }
-        return this.searchStrategy.findSuitableResource(load, restrictedResources)
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/FullSearch.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/FullSearch.kt
deleted file mode 100644
index 83c4abbdf44f1a1c2f3a27714d796580feedee49..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/FullSearch.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package theodolite.strategies.searchstrategy
-
-import mu.KotlinLogging
-import theodolite.execution.BenchmarkExecutor
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-
-private val logger = KotlinLogging.logger {}
-
-/**
- * [SearchStrategy] that executes experiment for provides resources in a linear-search-like fashion, but **without
- * stopping** once a suitable resource amount is found.
- *
- * @see LinearSearch for a SearchStrategy that stops once a suitable resource amount is found.
- *
- * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks.
- */
-class FullSearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmarkExecutor) {
-
-    override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? {
-        var minimalSuitableResources: Resource? = null
-        for (res in resources) {
-            logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" }
-            val result = this.benchmarkExecutor.runExperiment(load, res)
-            if (result && minimalSuitableResources == null) {
-                minimalSuitableResources = res
-            }
-        }
-        return minimalSuitableResources
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/GuessStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/GuessStrategy.kt
deleted file mode 100644
index 786a3baf159e94841c1f76c696f030718e8f768f..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/GuessStrategy.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package theodolite.strategies.searchstrategy
-
-import io.quarkus.runtime.annotations.RegisterForReflection
-import theodolite.util.Resource
-
-/**
- * Base class for the implementation of Guess strategies. Guess strategies are strategies to determine the resource
- * demand we start with in our initial guess search strategy.
- */
-
-@RegisterForReflection
-abstract class GuessStrategy {
-    /**
-     * Computing the resource demand for the initial guess search strategy to start with.
-     *
-     * @param resources List of all possible [Resource]s.
-     * @param lastLowestResource Previous resource demand needed for the given load.
-     *
-     * @return Returns the resource demand to start the initial guess search strategy with or null
-     */
-    abstract fun firstGuess(resources: List<Resource>, lastLowestResource: Resource?): Resource?
-}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/InitialGuessSearchStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/InitialGuessSearchStrategy.kt
deleted file mode 100644
index d97fb62cc9d37dd50122199e5d089c491784e511..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/InitialGuessSearchStrategy.kt
+++ /dev/null
@@ -1,93 +0,0 @@
-package theodolite.strategies.searchstrategy
-
-import mu.KotlinLogging
-import theodolite.execution.BenchmarkExecutor
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-import theodolite.util.Results
-
-private val logger = KotlinLogging.logger {}
-
-/**
- *  Search strategy implementation for determining the smallest suitable resource demand.
- *  Starting with a resource amount provided by a guess strategy.
- *
- * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks.
- * @param guessStrategy Strategy that provides us with a guess for the first resource amount.
- * @param results current results of all previously performed benchmarks.
- */
-class InitialGuessSearchStrategy(benchmarkExecutor: BenchmarkExecutor, guessStrategy: GuessStrategy, results: Results) :
-        SearchStrategy(benchmarkExecutor, guessStrategy, results) {
-
-    override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? {
-
-        if(resources.isEmpty()) {
-            logger.info { "You need to specify resources to be checked for the InitialGuessSearchStrategy to work." }
-            return null
-        }
-
-        if(guessStrategy == null){
-            logger.info { "Your InitialGuessSearchStrategy doesn't have a GuessStrategy. This is not supported." }
-            return null
-        }
-
-        if(results == null){
-            logger.info { "The results need to be initialized." }
-            return null
-        }
-
-
-        var lastLowestResource : Resource? = null
-
-        // Getting the lastLowestResource from results and calling firstGuess() with it
-        if (!results.isEmpty()) {
-            val maxLoad: LoadDimension? = this.results.getMaxBenchmarkedLoad(load)
-            lastLowestResource = this.results.getMinRequiredInstances(maxLoad)
-            if (lastLowestResource.get() == Int.MAX_VALUE) lastLowestResource = null
-        }
-        lastLowestResource = this.guessStrategy.firstGuess(resources, lastLowestResource)
-
-        if (lastLowestResource != null) {
-            val resourcesToCheck: List<Resource>
-            val startIndex: Int = resources.indexOf(lastLowestResource)
-
-            logger.info { "Running experiment with load '${load.get()}' and resources '${lastLowestResource.get()}'" }
-
-            // If the first experiment passes, starting downward linear search
-            // otherwise starting upward linear search
-            if (this.benchmarkExecutor.runExperiment(load, lastLowestResource)) {
-
-                resourcesToCheck = resources.subList(0, startIndex).reversed()
-                if (resourcesToCheck.isEmpty()) return lastLowestResource
-
-                var currentMin: Resource = lastLowestResource
-                for (res in resourcesToCheck) {
-
-                    logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" }
-                    if (this.benchmarkExecutor.runExperiment(load, res)) {
-                        currentMin = res
-                    }
-                }
-                return currentMin
-            }
-            else {
-                if (resources.size <= startIndex + 1) {
-                    logger.info{ "No more resources left to check." }
-                    return null
-                }
-                resourcesToCheck = resources.subList(startIndex + 1, resources.size)
-
-                for (res in resourcesToCheck) {
-
-                    logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" }
-                    if (this.benchmarkExecutor.runExperiment(load, res)) return res
-                }
-            }
-        }
-        else {
-            logger.info { "InitialGuessSearchStrategy called without lastLowestResource value, which is needed as a " +
-                    "starting point!" }
-        }
-        return null
-    }
-}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/LinearSearch.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/LinearSearch.kt
deleted file mode 100644
index 85deaf6fa75437199bfc560404eb5b40bb4a986a..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/LinearSearch.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package theodolite.strategies.searchstrategy
-
-import mu.KotlinLogging
-import theodolite.execution.BenchmarkExecutor
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-
-private val logger = KotlinLogging.logger {}
-
-/**
- *  Linear-search-like implementation for determining the smallest suitable number of instances.
- *
- * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks.
- */
-class LinearSearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmarkExecutor) {
-
-    override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? {
-        for (res in resources) {
-
-            logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" }
-            if (this.benchmarkExecutor.runExperiment(load, res)) return res
-        }
-        return null
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevResourceMinGuess.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevResourceMinGuess.kt
deleted file mode 100644
index 413eecea27279cd79bad155fbb7d5d18b674a12e..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevResourceMinGuess.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package theodolite.strategies.searchstrategy
-
-import theodolite.util.Resource
-
-/**
- * This Guess strategy takes the minimal resource demand of the previous load, which is given as an argument for the
- * firstGuess function.
- */
-
-class PrevResourceMinGuess() : GuessStrategy(){
-
-    /**
-     * @param resources List of all possible [Resource]s.
-     * @param lastLowestResource Previous resource demand needed for the given load.
-     *
-     * @return the value of lastLowestResource if given otherwise the first element of the resource list or null
-     */
-    override fun firstGuess(resources: List<Resource>, lastLowestResource: Resource?): Resource? {
-
-        if (lastLowestResource != null) return lastLowestResource
-        else if(resources.isNotEmpty()) return resources[0]
-        else return null
-    }
-}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/SearchStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/SearchStrategy.kt
deleted file mode 100644
index 97c723f2cfe459081cbb327f6860e48319c8f4f1..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/SearchStrategy.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package theodolite.strategies.searchstrategy
-
-import io.quarkus.runtime.annotations.RegisterForReflection
-import theodolite.execution.BenchmarkExecutor
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-import theodolite.util.Results
-
-/**
- *  Base class for the implementation for SearchStrategies. SearchStrategies determine the smallest suitable number of instances.
- *
- * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks.
- * @param guessStrategy Guess strategy for the initial resource amount in case the InitialGuessStrategy is selected.
- * @param results the [Results] object.
- */
-@RegisterForReflection
-abstract class SearchStrategy(val benchmarkExecutor: BenchmarkExecutor, val guessStrategy: GuessStrategy? = null,
-                              val results: Results? = null) {
-    /**
-     * Find smallest suitable resource from the specified resource list for the given load.
-     *
-     * @param load the [LoadDimension] to be tested.
-     * @param resources List of all possible [Resource]s.
-     *
-     * @return suitable resource for the specified load, or null if no suitable resource exists.
-     */
-    abstract fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource?
-}
diff --git a/theodolite/src/main/kotlin/theodolite/util/Config.kt b/theodolite/src/main/kotlin/theodolite/util/Config.kt
deleted file mode 100644
index afbf784e9d6d72939615e367b54891ecd95a3608..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/util/Config.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package theodolite.util
-
-import io.quarkus.runtime.annotations.RegisterForReflection
-import theodolite.strategies.searchstrategy.CompositeStrategy
-
-/**
- * Config class that represents a configuration of a theodolite run.
- *
- * @param loads the [LoadDimension] of the execution
- * @param resources the [Resource] of the execution
- * @param compositeStrategy the [CompositeStrategy] of the execution
- */
-@RegisterForReflection
-data class Config(
-    val loads: List<LoadDimension>,
-    val resources: List<Resource>,
-    val compositeStrategy: CompositeStrategy
-)
diff --git a/theodolite/src/main/kotlin/theodolite/util/LoadDimension.kt b/theodolite/src/main/kotlin/theodolite/util/LoadDimension.kt
deleted file mode 100644
index cf26da979b05f0a2bd82289ce371715ea0d67c93..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/util/LoadDimension.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-package theodolite.util
-
-import io.quarkus.runtime.annotations.RegisterForReflection
-
-/**
- * Representation of the load dimensions for a execution of theodolite.
- *
- * @param number the value of this [LoadDimension]
- * @param type [PatcherDefinition] of this [LoadDimension]
- */
-@RegisterForReflection
-data class LoadDimension(private val number: Int, private val type: List<PatcherDefinition>) {
-    /**
-     * @return the value of this load dimension.
-     */
-    fun get(): Int {
-        return this.number
-    }
-
-    /**
-     * @return the list of [PatcherDefinition]
-     */
-    fun getType(): List<PatcherDefinition> {
-        return this.type
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/util/Resource.kt b/theodolite/src/main/kotlin/theodolite/util/Resource.kt
deleted file mode 100644
index 1d6410aa4288e19817e3ba48bfd1bc0d85d006a2..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/util/Resource.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package theodolite.util
-
-import io.quarkus.runtime.annotations.RegisterForReflection
-
-/**
- * Representation of the resources for an execution of Theodolite.
- */
-@RegisterForReflection
-data class Resource(private val number: Int, private val type: List<PatcherDefinition>) {
-
-    /**
-     * @return the value of this resource.
-     */
-    fun get(): Int {
-        return this.number
-    }
-
-    /**
-     * @return the list of [PatcherDefinition]
-     */
-    fun getType(): List<PatcherDefinition> {
-        return this.type
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/util/Results.kt b/theodolite/src/main/kotlin/theodolite/util/Results.kt
deleted file mode 100644
index 2221c2e64f6dbc1776122f20793aa8d04d621d9d..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/util/Results.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-package theodolite.util
-
-import io.quarkus.runtime.annotations.RegisterForReflection
-
-/**
- * Central class that saves the state of an execution of Theodolite. For an execution, it is used to save the result of
- * individual experiments. Further, it is used by the RestrictionStrategy to
- * perform the [theodolite.strategies.restriction.RestrictionStrategy].
- */
-@RegisterForReflection
-class Results {
-    private val results: MutableMap<Pair<LoadDimension, Resource>, Boolean> = mutableMapOf()
-
-    /**
-     * Set the result for an experiment.
-     *
-     * @param experiment A pair that identifies the experiment by the [LoadDimension] and [Resource].
-     * @param successful the result of the experiment. Successful == true and Unsuccessful == false.
-     */
-    fun setResult(experiment: Pair<LoadDimension, Resource>, successful: Boolean) {
-        this.results[experiment] = successful
-    }
-
-    /**
-     * Get the result for an experiment.
-     *
-     * @param experiment A pair that identifies the experiment by the [LoadDimension] and [Resource].
-     * @return true if the experiment was successful and false otherwise. If the result has not been reported so far,
-     * null is returned.
-     *
-     * @see Resource
-     */
-    fun getResult(experiment: Pair<LoadDimension, Resource>): Boolean? {
-        return this.results[experiment]
-    }
-
-    /**
-     * Get the smallest suitable number of instances for a specified [LoadDimension].
-     *
-     * @param load the [LoadDimension]
-     *
-     * @return the smallest suitable number of resources. If the experiment was not executed yet,
-     * a @see Resource with the constant Int.MAX_VALUE as value is returned.
-     * If no experiments have been marked as either successful or unsuccessful
-     * yet, a Resource with the constant value Int.MIN_VALUE is returned.
-     */
-    fun getMinRequiredInstances(load: LoadDimension?): Resource {
-        if (this.results.isEmpty()) {
-            return Resource(Int.MIN_VALUE, emptyList())
-        }
-
-        var minRequiredInstances = Resource(Int.MAX_VALUE, emptyList())
-        for (experiment in results) {
-            // Get all successful experiments for requested load
-            if (experiment.key.first == load && experiment.value) {
-                if (experiment.key.second.get() < minRequiredInstances.get()) {
-                    // Found new smallest resources
-                    minRequiredInstances = experiment.key.second
-                }
-            }
-        }
-        return minRequiredInstances
-    }
-
-    /**
-     * Get the largest [LoadDimension] that has been reported executed successfully (or unsuccessfully) so far, for a
-     * [LoadDimension] and is smaller than the given [LoadDimension].
-     *
-     * @param load the [LoadDimension]
-     *
-     * @return the largest [LoadDimension] or null, if there is none for this [LoadDimension]
-     */
-    fun getMaxBenchmarkedLoad(load: LoadDimension): LoadDimension? {
-        var maxBenchmarkedLoad: LoadDimension? = null
-        for (experiment in results) {
-            if (experiment.key.first.get() <= load.get()) {
-                if (maxBenchmarkedLoad == null) {
-                    maxBenchmarkedLoad = experiment.key.first
-                } else if (maxBenchmarkedLoad.get() < experiment.key.first.get()) {
-                    maxBenchmarkedLoad = experiment.key.first
-                }
-            }
-        }
-        return maxBenchmarkedLoad
-    }
-
-    /**
-     * Checks whether the results are empty.
-     *
-     * @return true if [results] is empty.
-     */
-    fun isEmpty(): Boolean{
-        return results.isEmpty()
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/util/TypeName.kt b/theodolite/src/main/kotlin/theodolite/util/TypeName.kt
deleted file mode 100644
index f20fc7c9ce6757be75d9317e76c23a68b09914bd..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/util/TypeName.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package theodolite.util
-
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize
-import io.quarkus.runtime.annotations.RegisterForReflection
-
-/**
- * The TypeName encapsulates a list of [PatcherDefinition] along with a typeName that specifies for what the [PatcherDefinition] should be used.
- */
-@RegisterForReflection
-@JsonDeserialize
-class TypeName {
-    lateinit var typeName: String
-    lateinit var patchers: List<PatcherDefinition>
-}
diff --git a/theodolite/src/test/kotlin/MockServerUtils.kt b/theodolite/src/test/kotlin/MockServerUtils.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0c8da45cd5d2dab948f9ccba1c2f4917050bb040
--- /dev/null
+++ b/theodolite/src/test/kotlin/MockServerUtils.kt
@@ -0,0 +1,20 @@
+import io.fabric8.kubernetes.api.model.APIResourceListBuilder
+import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer
+
+fun KubernetesServer.registerResource(context: ResourceDefinitionContext) {
+    val apiResourceList = APIResourceListBuilder()
+        .addNewResource()
+            .withName(context.plural)
+            .withKind(context.kind)
+            .withNamespaced(context.isNamespaceScoped)
+        .endResource()
+        .build()
+
+    this
+        .expect()
+        .get()
+        .withPath("/apis/${context.group}/${context.version}")
+        .andReturn(200, apiResourceList)
+        .always()
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/util/IOHandlerTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/core/IOHandlerTest.kt
similarity index 91%
rename from theodolite/src/test/kotlin/theodolite/util/IOHandlerTest.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/core/IOHandlerTest.kt
index f84536bfc029a829c1798293938386965eedcf47..65e84d7dd37eb5b68f77bc2d47d212db2f720a90 100644
--- a/theodolite/src/test/kotlin/theodolite/util/IOHandlerTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/core/IOHandlerTest.kt
@@ -1,4 +1,4 @@
-package theodolite.util
+package rocks.theodolite.core
 
 import com.google.gson.GsonBuilder
 import io.quarkus.test.junit.QuarkusTest
@@ -12,7 +12,6 @@ import org.junit.rules.TemporaryFolder
 import org.junitpioneer.jupiter.ClearEnvironmentVariable
 import org.junitpioneer.jupiter.SetEnvironmentVariable
 
-
 const val FOLDER_URL = "Test-Folder"
 
 @QuarkusTest
@@ -56,11 +55,12 @@ internal class IOHandlerTest {
             columns = columns
         )
 
-        var expected = "Fruit,Color\n"
-        testContent.forEach { expected += it[0] + "," + it[1] + "\n" }
+        val expected = (listOf(listOf("Fruit", "Color")) + testContent)
+            .map { "${it[0]},${it[1]}" }
+            .reduce { left, right -> left + System.lineSeparator() + right }
 
         assertEquals(
-            expected.trim(),
+            expected,
             IOHandler().readFileAsString("${folder.absolutePath}/test-file.csv")
         )
     }
@@ -69,14 +69,14 @@ internal class IOHandlerTest {
     fun testWriteToJSONFile() {
         temporaryFolder.create()
         val folder = temporaryFolder.newFolder(FOLDER_URL)
-        val testContent = Resource(0, emptyList())
+        val testContentResource = 0
 
         IOHandler().writeToJSONFile(
             fileURL = "${folder.absolutePath}/test-file.json",
-            objectToSave = testContent
+            objectToSave = testContentResource
         )
 
-        val expected = GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting().create().toJson(testContent)
+        val expected = GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting().create().toJson(testContentResource)
 
         assertEquals(
             expected,
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/core/ResultsTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/core/ResultsTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2dbeb44b90f780975af884028335a7e398c7cfdc
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/core/ResultsTest.kt
@@ -0,0 +1,91 @@
+package rocks.theodolite.core
+
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertNotNull
+import org.junit.jupiter.api.Test
+import rocks.theodolite.core.strategies.Metric
+
+@QuarkusTest
+internal class ResultsTest {
+
+    @Test
+    fun testMinRequiredInstancesWhenSuccessfulDemand() {
+        val results = Results(Metric.from("demand"))
+        results.setResult(Pair(10000, 1), true)
+        results.setResult(Pair(10000, 2), true)
+        results.setResult(Pair(20000, 1), false)
+        results.setResult(Pair(20000, 2), true)
+
+        val minRequiredInstances = results.getOptYDimensionValue(20000)
+
+        assertNotNull(minRequiredInstances)
+        assertEquals(2, minRequiredInstances)
+    }
+
+    @Test
+    fun testGetMaxBenchmarkedLoadWhenAllSuccessfulDemand() {
+        val results = Results(Metric.from("demand"))
+        results.setResult(Pair(10000, 1), true)
+        results.setResult(Pair(10000, 2), true)
+
+        val test1 = results.getMaxBenchmarkedXDimensionValue(100000)
+
+        assertNotNull(test1)
+        assertEquals(10000, test1)
+    }
+
+    @Test
+    fun testGetMaxBenchmarkedLoadWhenLargestNotSuccessfulDemand() {
+        val results = Results(Metric.from("demand"))
+        results.setResult(Pair(10000, 1), true)
+        results.setResult(Pair(10000, 2), true)
+        results.setResult(Pair(20000, 1), false)
+
+        val test2 = results.getMaxBenchmarkedXDimensionValue(100000)
+
+        assertNotNull(test2)
+        assertEquals(20000, test2)
+    }
+
+    @Test
+    fun testMaxRequiredInstancesWhenSuccessfulCapacity() {
+        val results = Results(Metric.from("capacity"))
+        results.setResult(Pair(10000, 1), true)
+        results.setResult(Pair(20000, 1), false)
+        results.setResult(Pair(10000, 2), true)
+        results.setResult(Pair(20000, 2), true)
+
+        val maxRequiredInstances = results.getOptYDimensionValue(2)
+
+        assertNotNull(maxRequiredInstances)
+        assertEquals(20000, maxRequiredInstances)
+    }
+
+
+    @Test
+    fun testGetMaxBenchmarkedLoadWhenAllSuccessfulCapacity() {
+        val results = Results(Metric.from("capacity"))
+        results.setResult(Pair(10000, 1), true)
+        results.setResult(Pair(10000, 2), true)
+
+        val test1 = results.getMaxBenchmarkedXDimensionValue(5)
+
+        assertNotNull(test1)
+        assertEquals(2, test1)
+    }
+
+    @Test
+    fun testGetMaxBenchmarkedLoadWhenLargestNotSuccessfulCapacity() {
+        val results = Results(Metric.from("capacity"))
+        results.setResult(Pair(10000, 1), true)
+        results.setResult(Pair(20000, 1), true)
+        results.setResult(Pair(10000, 2), false)
+
+
+        val test2 = results.getMaxBenchmarkedXDimensionValue(5)
+
+        assertNotNull(test2)
+        assertEquals(2, test2)
+    }
+}
diff --git a/theodolite/src/test/kotlin/theodolite/strategies/restriction/LowerBoundRestrictionTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/LowerBoundRestrictionTest.kt
similarity index 53%
rename from theodolite/src/test/kotlin/theodolite/strategies/restriction/LowerBoundRestrictionTest.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/LowerBoundRestrictionTest.kt
index b368647e314a4d803b444268c8218aefbee00ad4..79fadb4867a155ee7b4dc86e4bb165947a4f15a4 100644
--- a/theodolite/src/test/kotlin/theodolite/strategies/restriction/LowerBoundRestrictionTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/LowerBoundRestrictionTest.kt
@@ -1,25 +1,21 @@
-package theodolite.strategies.restriction
+package rocks.theodolite.core.strategies.restrictionstrategy
 
 import org.junit.jupiter.api.Assertions.assertEquals
 import org.junit.jupiter.api.Assertions.assertNotNull
 import org.junit.jupiter.api.Disabled
 import org.junit.jupiter.api.Test
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-import theodolite.util.Results
+import rocks.theodolite.core.strategies.Metric
+import rocks.theodolite.core.strategies.restrictionstrategy.LowerBoundRestriction
+import rocks.theodolite.core.Results
 
 internal class LowerBoundRestrictionTest {
 
     @Test
     fun testNoPreviousResults() {
-        val results = Results()
+        val results = Results(Metric.from("demand"))
         val strategy = LowerBoundRestriction(results)
-        val load = buildLoadDimension(10000)
-        val resources = listOf(
-            buildResourcesDimension(1),
-            buildResourcesDimension(2),
-            buildResourcesDimension(3)
-        )
+        val load = 10000
+        val resources = listOf(1, 2, 3)
         val restriction = strategy.apply(load, resources)
 
         assertEquals(3, restriction.size)
@@ -28,17 +24,13 @@ internal class LowerBoundRestrictionTest {
 
     @Test
     fun testWithSuccessfulPreviousResults() {
-        val results = Results()
+        val results = Results(Metric.from("demand"))
         results.setResult(10000, 1, true)
         results.setResult(20000, 1, false)
         results.setResult(20000, 2, true)
         val strategy = LowerBoundRestriction(results)
-        val load = buildLoadDimension(30000)
-        val resources = listOf(
-            buildResourcesDimension(1),
-            buildResourcesDimension(2),
-            buildResourcesDimension(3)
-        )
+        val load = 30000
+        val resources = listOf(1, 2, 3)
         val restriction = strategy.apply(load, resources)
 
         assertEquals(2, restriction.size)
@@ -49,70 +41,54 @@ internal class LowerBoundRestrictionTest {
     @Disabled
     fun testWithNoSuccessfulPreviousResults() {
         // This test is currently not implemented this way, but might later be the desired behavior.
-        val results = Results()
+        val results = Results(Metric.from("demand"))
         results.setResult(10000, 1, true)
         results.setResult(20000, 1, false)
         results.setResult(20000, 2, false)
         results.setResult(20000, 3, false)
         val strategy = LowerBoundRestriction(results)
-        val load = buildLoadDimension(30000)
-        val resources = listOf(
-            buildResourcesDimension(1),
-            buildResourcesDimension(2),
-            buildResourcesDimension(3)
-        )
+        val load = 30000
+        val resources = listOf(1, 2, 3)
         val restriction = strategy.apply(load, resources)
 
         assertEquals(0, restriction.size)
-        assertEquals(emptyList<Resource>(), restriction)
+        assertEquals(emptyList<Int>(), restriction)
     }
 
 
     @Test
     fun testNoPreviousResults2() {
-        val results = Results()
+        val results = Results(Metric.from("demand"))
         results.setResult(10000, 1, true)
         results.setResult(20000, 2, true)
         results.setResult(10000, 1, false)
         results.setResult(20000, 2, true)
 
-        val minRequiredInstances = results.getMinRequiredInstances(LoadDimension(20000, emptyList()))
+        val minRequiredInstances = results.getOptYDimensionValue(20000)
 
         assertNotNull(minRequiredInstances)
-        assertEquals(2, minRequiredInstances!!.get())
+        assertEquals(2, minRequiredInstances!!)
     }
 
     @Test
     @Disabled
     fun testMinRequiredInstancesWhenNotSuccessful() {
         // This test is currently not implemented this way, but might later be the desired behavior.
-        val results = Results()
+        val results = Results(Metric.from("demand"))
         results.setResult(10000, 1, true)
         results.setResult(20000, 2, true)
         results.setResult(10000, 1, false)
         results.setResult(20000, 2, false)
 
-        val minRequiredInstances = results.getMinRequiredInstances(LoadDimension(20000, emptyList()))
+        val minRequiredInstances = results.getOptYDimensionValue(20000)
 
         assertNotNull(minRequiredInstances)
-        assertEquals(2, minRequiredInstances!!.get())
+        assertEquals(2, minRequiredInstances!!)
     }
 
-    private fun buildLoadDimension(load: Int): LoadDimension {
-        return LoadDimension(load, emptyList())
-    }
 
-    private fun buildResourcesDimension(resources: Int): Resource {
-        return Resource(resources, emptyList())
-    }
 
-    private fun Results.setResult(load: Int, resources: Int, successful: Boolean) {
-        this.setResult(
-            Pair(
-                buildLoadDimension(load),
-                buildResourcesDimension(resources)
-            ),
-            successful
-        )
+    private fun Results.setResult(load: Int, resource: Int, successful: Boolean) {
+        this.setResult(Pair(load, resource),successful)
     }
 }
diff --git a/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/core/strategies/searchstrategy/InitialGuessSearchStrategyTest.kt
similarity index 52%
rename from theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/core/strategies/searchstrategy/InitialGuessSearchStrategyTest.kt
index 1af6f548b219697009c688ace712a9f7f5620bd0..820dc7564aac2497a2884ca004f15110bc5465f7 100644
--- a/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/core/strategies/searchstrategy/InitialGuessSearchStrategyTest.kt
@@ -1,15 +1,15 @@
-package theodolite
+package rocks.theodolite.core.strategies.searchstrategy
 
 import io.quarkus.test.junit.QuarkusTest
 import org.junit.jupiter.api.Assertions.assertEquals
 import org.junit.jupiter.api.Test
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.strategies.searchstrategy.InitialGuessSearchStrategy
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-import theodolite.util.Results
+import rocks.theodolite.core.strategies.Metric
 import mu.KotlinLogging
-import theodolite.strategies.searchstrategy.PrevResourceMinGuess
+import rocks.theodolite.kubernetes.TestBenchmarkDeploymentBuilder
+import rocks.theodolite.kubernetes.TestExperimentRunnerImpl
+import rocks.theodolite.core.strategies.guessstrategy.PrevInstanceOptGuess
+import rocks.theodolite.core.Results
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark.Slo
 
 private val logger = KotlinLogging.logger {}
 
@@ -27,23 +27,23 @@ class InitialGuessSearchStrategyTest {
             arrayOf(false, false, false, false, false, false, true),
             arrayOf(false, false, false, false, false, false, false)
         )
-        val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, emptyList()) }
-        val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) }
-        val results = Results()
-        val benchmark = TestBenchmark()
-        val guessStrategy = PrevResourceMinGuess()
-        val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo()
-        val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5)
+        val mockLoads: List<Int> = (0..6).toList()
+        val mockResources: List<Int> = (0..6).toList()
+        val results = Results(Metric.from("demand"))
+        val benchmarkDeploymentBuilder = TestBenchmarkDeploymentBuilder()
+        val guessStrategy = PrevInstanceOptGuess()
+        val sloChecker = Slo()
+        val benchmarkExecutor = TestExperimentRunnerImpl(results, mockResults, benchmarkDeploymentBuilder, listOf(sloChecker), 0, 0, 5)
         val strategy = InitialGuessSearchStrategy(benchmarkExecutor,guessStrategy, results)
 
-        val actual: ArrayList<Resource?> = ArrayList()
-        val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 3, 4, 6).map { x -> Resource(x, emptyList()) })
+        val actual: ArrayList<Int?> = ArrayList()
+        val expected: ArrayList<Int?> = ArrayList(listOf(0, 2, 2, 3, 4, 6))
         expected.add(null)
 
         for (load in mockLoads) {
-            val returnVal : Resource? = strategy.findSuitableResource(load, mockResources)
+            val returnVal : Int? = strategy.findSuitableResource(load, mockResources)
             if(returnVal != null) {
-                logger.info { "returnVal '${returnVal.get()}'" }
+                logger.info { "returnVal '${returnVal}'" }
             }
             else {
                 logger.info { "returnVal is null." }
@@ -65,23 +65,23 @@ class InitialGuessSearchStrategyTest {
             arrayOf(false, false, false, false, false, false, true),
             arrayOf(false, false, false, false, false, false, false)
         )
-        val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, emptyList()) }
-        val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) }
-        val results = Results()
-        val benchmark = TestBenchmark()
-        val guessStrategy = PrevResourceMinGuess()
-        val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo()
-        val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5)
+        val mockLoads: List<Int> = (0..6).toList()
+        val mockResources: List<Int> = (0..6).toList()
+        val results = Results(Metric.from("demand"))
+        val benchmarkDeploymentBuilder = TestBenchmarkDeploymentBuilder()
+        val guessStrategy = PrevInstanceOptGuess()
+        val sloChecker = Slo()
+        val benchmarkExecutor = TestExperimentRunnerImpl(results, mockResults, benchmarkDeploymentBuilder, listOf(sloChecker), 0, 0, 5)
         val strategy = InitialGuessSearchStrategy(benchmarkExecutor,guessStrategy, results)
 
-        val actual: ArrayList<Resource?> = ArrayList()
-        val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 1, 4, 6).map { x -> Resource(x, emptyList()) })
+        val actual: ArrayList<Int?> = ArrayList()
+        val expected: ArrayList<Int?> = ArrayList(listOf(0, 2, 2, 1, 4, 6))
         expected.add(null)
 
         for (load in mockLoads) {
-            val returnVal : Resource? = strategy.findSuitableResource(load, mockResources)
+            val returnVal : Int? = strategy.findSuitableResource(load, mockResources)
             if(returnVal != null) {
-                logger.info { "returnVal '${returnVal.get()}'" }
+                logger.info { "returnVal '${returnVal}'" }
             }
             else {
                 logger.info { "returnVal is null." }
@@ -103,24 +103,24 @@ class InitialGuessSearchStrategyTest {
                 arrayOf(false, false, false, false, false, false, true),
                 arrayOf(false, false, false, false, false, false, false)
         )
-        val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, emptyList()) }
-        val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) }
-        val results = Results()
-        val benchmark = TestBenchmark()
-        val guessStrategy = PrevResourceMinGuess()
-        val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo()
-        val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5)
+        val mockLoads: List<Int> = (0..6).toList()
+        val mockResources: List<Int> = (0..6).toList()
+        val results = Results(Metric.from("demand"))
+        val benchmarkDeploymentBuilder = TestBenchmarkDeploymentBuilder()
+        val guessStrategy = PrevInstanceOptGuess()
+        val sloChecker = Slo()
+        val benchmarkExecutor = TestExperimentRunnerImpl(results, mockResults, benchmarkDeploymentBuilder, listOf(sloChecker), 0, 0, 5)
         val strategy = InitialGuessSearchStrategy(benchmarkExecutor, guessStrategy, results)
 
-        val actual: ArrayList<Resource?> = ArrayList()
-        var expected: ArrayList<Resource?> = ArrayList(listOf(2, 3, 0, 4, 6).map { x -> Resource(x, emptyList()) })
+        val actual: ArrayList<Int?> = ArrayList()
+        var expected: ArrayList<Int?> = ArrayList(listOf(2, 3, 0, 4, 6))
         expected.add(null)
         expected = ArrayList(listOf(null) + expected)
 
         for (load in mockLoads) {
-            val returnVal : Resource? = strategy.findSuitableResource(load, mockResources)
+            val returnVal : Int? = strategy.findSuitableResource(load, mockResources)
             if(returnVal != null) {
-                logger.info { "returnVal '${returnVal.get()}'" }
+                logger.info { "returnVal '${returnVal}'" }
             }
             else {
                 logger.info { "returnVal is null." }
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/core/strategies/searchstrategy/RestrictionSearchTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/core/strategies/searchstrategy/RestrictionSearchTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..bae944801fcacf40431559a0e7ddeb78923d2173
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/core/strategies/searchstrategy/RestrictionSearchTest.kt
@@ -0,0 +1,148 @@
+package rocks.theodolite.core.strategies.searchstrategy
+
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
+import rocks.theodolite.kubernetes.TestBenchmarkDeploymentBuilder
+import rocks.theodolite.kubernetes.TestExperimentRunnerImpl
+import rocks.theodolite.core.strategies.Metric
+import rocks.theodolite.core.strategies.restrictionstrategy.LowerBoundRestriction
+import rocks.theodolite.core.Results
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark.Slo
+
+@QuarkusTest
+class RestrictionSearchTest {
+
+
+    @Test
+    fun restrictionSearchTestLinearSearch() {
+        val mockResults = arrayOf(
+            arrayOf(true, true, true, true, true, true, true),
+            arrayOf(false, false, true, true, true, true, true),
+            arrayOf(false, false, true, true, true, true, true),
+            arrayOf(false, false, false, true, true, true, true),
+            arrayOf(false, false, false, false, true, true, true),
+            arrayOf(false, false, false, false, false, false, true),
+            arrayOf(false, false, false, false, false, false, false)
+        )
+        val mockLoads: List<Int> = (0..6).toList()
+        val mockResources: List<Int> = (0..6).toList()
+        val results = Results(Metric.from("demand"))
+        val benchmarkDeploymentBuilder = TestBenchmarkDeploymentBuilder()
+        val sloChecker = Slo()
+        val benchmarkExecutor = TestExperimentRunnerImpl(results, mockResults, benchmarkDeploymentBuilder, listOf(sloChecker), 0, 0, 5)
+        val linearSearch = LinearSearch(benchmarkExecutor)
+        val lowerBoundRestriction = LowerBoundRestriction(results)
+        val strategy =
+            RestrictionSearch(benchmarkExecutor, linearSearch, setOf(lowerBoundRestriction))
+
+        val actual: ArrayList<Int?> = ArrayList()
+        val expected: ArrayList<Int?> = ArrayList(listOf(0, 2, 2, 3, 4, 6))
+        expected.add(null)
+
+        for (load in mockLoads) {
+            actual.add(strategy.findSuitableResource(load, mockResources))
+        }
+
+        assertEquals(actual, expected)
+    }
+
+    @Test
+    fun restrictionSearchTestFullSearch() {
+        val mockResults = arrayOf(
+                arrayOf(true, true, true, true, true, true, true),
+                arrayOf(false, false, true, true, true, true, true),
+                arrayOf(false, false, true, true, true, true, true),
+                arrayOf(false, false, false, true, true, true, true),
+                arrayOf(false, false, false, false, true, true, true),
+                arrayOf(false, false, false, false, false, false, true),
+                arrayOf(false, false, false, false, false, false, false)
+        )
+        val mockLoads: List<Int> = (0..6).toList()
+        val mockResources: List<Int> = (0..6).toList()
+        val results = Results(Metric.from("demand"))
+        val benchmarkDeploymentBuilder = TestBenchmarkDeploymentBuilder()
+        val sloChecker = Slo()
+        val benchmarkExecutor = TestExperimentRunnerImpl(results, mockResults, benchmarkDeploymentBuilder, listOf(sloChecker), 0, 0, 5)
+        val fullSearch = FullSearch(benchmarkExecutor)
+        val lowerBoundRestriction = LowerBoundRestriction(results)
+        val strategy =
+                RestrictionSearch(benchmarkExecutor, fullSearch, setOf(lowerBoundRestriction))
+
+        val actual: ArrayList<Int?> = ArrayList()
+        val expected: ArrayList<Int?> = ArrayList(listOf(0, 2, 2, 3, 4, 6))
+        expected.add(null)
+
+        for (load in mockLoads) {
+            actual.add(strategy.findSuitableResource(load, mockResources))
+        }
+
+        assertEquals(actual, expected)
+    }
+
+    @Test
+    fun restrictionSearchTestBinarySearch() {
+        val mockResults = arrayOf(
+            arrayOf(true, true, true, true, true, true, true),
+            arrayOf(false, false, true, true, true, true, true),
+            arrayOf(false, false, true, true, true, true, true),
+            arrayOf(false, false, false, true, true, true, true),
+            arrayOf(false, false, false, false, true, true, true),
+            arrayOf(false, false, false, false, false, false, true),
+            arrayOf(false, false, false, false, false, false, false)
+        )
+        val mockLoads: List<Int> = (0..6).toList()
+        val mockResources: List<Int> = (0..6).toList()
+        val results = Results(Metric.from("demand"))
+        val benchmarkDeploymentBuilder = TestBenchmarkDeploymentBuilder()
+        val sloChecker = Slo()
+        val benchmarkExecutorImpl =
+            TestExperimentRunnerImpl(results, mockResults, benchmarkDeploymentBuilder, listOf(sloChecker), 0, 0, 0)
+        val binarySearch = BinarySearch(benchmarkExecutorImpl)
+        val lowerBoundRestriction = LowerBoundRestriction(results)
+        val strategy = RestrictionSearch(benchmarkExecutorImpl, binarySearch, setOf(lowerBoundRestriction))
+
+        val actual: ArrayList<Int?> = ArrayList()
+        val expected: ArrayList<Int?> = ArrayList(listOf(0, 2, 2, 3, 4, 6))
+        expected.add(null)
+
+        for (load in mockLoads) {
+            actual.add(strategy.findSuitableResource(load, mockResources))
+        }
+
+        assertEquals(actual, expected)
+    }
+
+    @Test
+    fun restrictionSearchTestBinarySearch2() {
+        val mockResults = arrayOf(
+            arrayOf(true, true, true, true, true, true, true, true),
+            arrayOf(false, false, true, true, true, true, true, true),
+            arrayOf(false, false, true, true, true, true, true, true),
+            arrayOf(false, false, false, true, true, true, true, true),
+            arrayOf(false, false, false, false, true, true, true, true),
+            arrayOf(false, false, false, false, false, false, true, true),
+            arrayOf(false, false, false, false, false, false, false, true)
+        )
+        val mockLoads: List<Int> = (0..6).toList()
+        val mockResources: List<Int> = (0..7).toList()
+        val results = Results(Metric.from("demand"))
+        val benchmarkDeploymentBuilder = TestBenchmarkDeploymentBuilder()
+        val sloChecker = Slo()
+        val benchmarkExecutor = TestExperimentRunnerImpl(results, mockResults, benchmarkDeploymentBuilder, listOf(sloChecker), 0, 0, 0)
+        val binarySearch = BinarySearch(benchmarkExecutor)
+        val lowerBoundRestriction = LowerBoundRestriction(results)
+        val strategy =
+            RestrictionSearch(benchmarkExecutor, binarySearch, setOf(lowerBoundRestriction))
+
+        val actual: ArrayList<Int?> = ArrayList()
+        val expected: ArrayList<Int?> =
+            ArrayList(listOf(0, 2, 2, 3, 4, 6, 7))
+
+        for (load in mockLoads) {
+            actual.add(strategy.findSuitableResource(load, mockResources))
+        }
+
+        assertEquals(actual, expected)
+    }
+}
diff --git a/theodolite/src/test/kotlin/theodolite/benchmark/ActionCommandTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ActionCommandTest.kt
similarity index 88%
rename from theodolite/src/test/kotlin/theodolite/benchmark/ActionCommandTest.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ActionCommandTest.kt
index 0e40fca5caf9fe721c547e09d2ba22c25860a1bf..afc86fc2663d07ab3711533f0d01797bd7311363 100644
--- a/theodolite/src/test/kotlin/theodolite/benchmark/ActionCommandTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ActionCommandTest.kt
@@ -1,4 +1,4 @@
-package theodolite.benchmark
+package rocks.theodolite.kubernetes
 
 import io.fabric8.kubernetes.api.model.Pod
 import io.fabric8.kubernetes.api.model.PodBuilder
@@ -8,9 +8,9 @@ import io.fabric8.kubernetes.client.utils.Utils
 import io.quarkus.test.junit.QuarkusTest
 import org.junit.jupiter.api.*
 import org.junit.jupiter.api.Assertions.assertEquals
-import theodolite.execution.operator.TheodoliteController
-import theodolite.execution.operator.TheodoliteOperator
-import theodolite.util.ActionCommandFailedException
+import rocks.theodolite.kubernetes.operator.TheodoliteController
+import rocks.theodolite.kubernetes.operator.TheodoliteOperator
+
 
 @QuarkusTest
 class ActionCommandTest {
@@ -20,11 +20,10 @@ class ActionCommandTest {
     @BeforeEach
     fun setUp() {
         server.before()
-        val operator = TheodoliteOperator()
+        val operator = TheodoliteOperator(server.client)
         this.controller = operator.getController(
-            client = server.client,
-            executionStateHandler = operator.getExecutionStateHandler(client = server.client),
-            benchmarkStateChecker = operator.getBenchmarkStateChecker(client = server.client)
+            executionStateHandler = operator.getExecutionStateHandler(),
+            benchmarkStateChecker = operator.getBenchmarkStateChecker()
         )
 
         val pod: Pod = PodBuilder().withNewMetadata()
@@ -102,7 +101,7 @@ class ActionCommandTest {
         val action = Action()
         action.selector = ActionSelector()
         action.selector.pod = PodSelector()
-        action.selector.pod.matchLabels = mutableMapOf("app" to "pod")
+        action.selector.pod.matchLabels = mapOf("app" to "pod")
         action.exec = Command()
         action.exec.command = arrayOf("ls")
         action.exec.timeoutSeconds = 10L
@@ -118,7 +117,7 @@ class ActionCommandTest {
         val action = Action()
         action.selector = ActionSelector()
         action.selector.pod = PodSelector()
-        action.selector.pod.matchLabels = mutableMapOf("app" to "pod")
+        action.selector.pod.matchLabels = mapOf("app" to "pod")
         action.exec = Command()
         action.exec.command = arrayOf("error-command")
         action.exec.timeoutSeconds = 10L
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ConfigMapResourceSetTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ConfigMapResourceSetTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..87058706c1a315c98ba098e6c5835f3a57343112
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ConfigMapResourceSetTest.kt
@@ -0,0 +1,265 @@
+package rocks.theodolite.kubernetes
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import io.fabric8.kubernetes.api.model.*
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder
+import io.fabric8.kubernetes.api.model.apps.StatefulSet
+import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder
+import io.fabric8.kubernetes.client.dsl.MixedOperation
+import io.fabric8.kubernetes.client.dsl.Resource
+import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer
+import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.kubernetes.client.KubernetesTestServer
+import io.quarkus.test.kubernetes.client.WithKubernetesTestServer
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertThrows
+import registerResource
+import rocks.theodolite.kubernetes.model.crd.BenchmarkCRDummy
+import rocks.theodolite.kubernetes.operator.ExecutionClient
+import rocks.theodolite.kubernetes.model.crd.BenchmarkCRD
+import rocks.theodolite.kubernetes.model.crd.ExecutionCRD
+import java.io.FileInputStream
+
+// TODO move somewhere else
+typealias BenchmarkClient = MixedOperation<BenchmarkCRD, KubernetesResourceList<BenchmarkCRD>, Resource<BenchmarkCRD>>
+
+@QuarkusTest
+@WithKubernetesTestServer
+internal class ConfigMapResourceSetTest {
+
+    @KubernetesTestServer
+    private lateinit var server: KubernetesServer
+
+    private val objectMapper: ObjectMapper = ObjectMapper()
+
+    private lateinit var executionClient: ExecutionClient
+    private lateinit var benchmarkClient: BenchmarkClient
+
+    @BeforeEach
+    fun setUp() {
+        server.before()
+        this.server.client
+            .apiextensions().v1()
+            .customResourceDefinitions()
+            .load(FileInputStream("crd/crd-execution.yaml"))
+            .create()
+        this.server.client
+            .apiextensions().v1()
+            .customResourceDefinitions()
+            .load(FileInputStream("crd/crd-benchmark.yaml"))
+            .create()
+
+        this.executionClient = this.server.client.resources(ExecutionCRD::class.java)
+        this.benchmarkClient = this.server.client.resources(BenchmarkCRD::class.java)
+    }
+
+    @AfterEach
+    fun tearDown() {
+        server.after()
+    }
+
+    private fun deployAndGetResource(vararg resources: HasMetadata): ConfigMapResourceSet {
+        val configMap = ConfigMapBuilder()
+            .withNewMetadata().withName("test-configmap").endMetadata()
+            .let {
+                resources.foldIndexed(it) {
+                    i, b, r -> b.addToData("resource_$i.yaml", objectMapper.writeValueAsString(r))
+                }
+            }
+            .build()
+
+        server.client.configMaps().createOrReplace(configMap)
+
+        val resourceSet = ConfigMapResourceSet()
+        resourceSet.name = "test-configmap"
+
+        return resourceSet
+    }
+
+    @Test
+    fun testLoadDeployment() {
+        val resource = DeploymentBuilder()
+            .withNewSpec()
+            .endSpec()
+            .withNewMetadata()
+            .withName("test-deployment")
+            .endMetadata()
+            .build()
+
+        val createdResource = deployAndGetResource(resource).getResourceSet(server.client)
+        assertEquals(1, createdResource.size)
+        assertTrue(createdResource.toList().first().second is Deployment)
+        assertTrue(createdResource.toList().first().second.toString().contains(other = resource.metadata.name))
+    }
+
+    @Test
+    fun testLoadStateFulSet() {
+        val resource = StatefulSetBuilder()
+            .withNewSpec()
+            .endSpec()
+            .withNewMetadata()
+            .withName("test-sts")
+            .endMetadata()
+            .build()
+
+        val createdResource = deployAndGetResource(resource).getResourceSet(server.client)
+        assertEquals(1, createdResource.size)
+        assertTrue(createdResource.toList().first().second is StatefulSet)
+        assertTrue(createdResource.toList().first().second.toString().contains(other = resource.metadata.name))
+    }
+
+    @Test
+    fun testLoadService() {
+        val resource = ServiceBuilder()
+            .withNewSpec()
+            .endSpec()
+            .withNewMetadata()
+            .withName("test-service")
+            .endMetadata()
+            .build()
+
+        val createdResource = deployAndGetResource(resource).getResourceSet(server.client)
+        assertEquals(1, createdResource.size)
+        assertTrue(createdResource.toList().first().second is Service)
+        assertTrue(createdResource.toList().first().second.toString().contains(other = resource.metadata.name))
+    }
+
+    @Test
+    fun testLoadConfigMap() {
+        val resource = ConfigMapBuilder()
+            .withNewMetadata()
+            .withName("test-configmap")
+            .endMetadata()
+            .build()
+
+        val createdResource = deployAndGetResource(resource).getResourceSet(server.client)
+        assertEquals(1, createdResource.size)
+        assertTrue(createdResource.toList().first().second is ConfigMap)
+        assertTrue(createdResource.toList().first().second.toString().contains(other = resource.metadata.name))
+    }
+
+    @Test
+    fun testLoadExecution() {
+        val stream = javaClass.getResourceAsStream("/k8s-resource-files/test-execution.yaml")
+        val execution = this.executionClient.load(stream).get()
+        val createdResource = deployAndGetResource(execution).getResourceSet(server.client)
+
+        assertEquals(1, createdResource.size)
+        val loadedResource = createdResource.toList().first().second
+        assertTrue(loadedResource is ExecutionCRD)
+        assertEquals("example-execution", loadedResource.metadata.name)
+
+
+    }
+
+    @Test
+    fun testLoadBenchmark() {
+        val benchmark = BenchmarkCRDummy("example-benchmark").getCR()
+        val createdResource = deployAndGetResource(benchmark).getResourceSet(server.client)
+
+        assertEquals(1, createdResource.size)
+        val loadedResource = createdResource.toList().first().second
+        assertTrue(loadedResource is BenchmarkCRD)
+        assertEquals("example-benchmark", loadedResource.metadata.name)
+    }
+
+    @Test
+    fun testLoadServiceMonitor() {
+        val serviceMonitorContext = ResourceDefinitionContext.Builder()
+            .withGroup("monitoring.coreos.com")
+            .withKind("ServiceMonitor")
+            .withPlural("servicemonitors")
+            .withNamespaced(true)
+            .withVersion("v1")
+            .build()
+        server.registerResource(serviceMonitorContext)
+
+        val stream = javaClass.getResourceAsStream("/k8s-resource-files/test-service-monitor.yaml")
+        val serviceMonitor = server.client.load(stream).get()[0]
+        val createdResource = deployAndGetResource(serviceMonitor).getResourceSet(server.client)
+
+        assertEquals(1, createdResource.size)
+        val loadedResource = createdResource.toList().first().second
+        assertTrue(loadedResource is GenericKubernetesResource)
+        assertEquals("ServiceMonitor", loadedResource.kind)
+        assertEquals("test-service-monitor", loadedResource.metadata.name)
+    }
+
+    @Test
+    fun testMultipleFiles(){
+        val deployment = DeploymentBuilder()
+            .withNewSpec()
+            .endSpec()
+            .withNewMetadata()
+            .withName("test-deployment")
+            .endMetadata()
+            .build()
+        val configMap = ConfigMapBuilder()
+            .withNewMetadata()
+            .withName("test-configmap")
+            .endMetadata()
+            .build()
+
+        val createdResourceSet = deployAndGetResource(deployment, configMap).getResourceSet(server.client)
+
+        assertEquals(2, createdResourceSet.size )
+        assert(createdResourceSet.toList()[0].second is Deployment)
+        assert(createdResourceSet.toList()[1].second is ConfigMap)
+    }
+
+    @Test
+    fun testFilesRestricted() {
+        val deployment = DeploymentBuilder()
+            .withNewSpec()
+            .endSpec()
+            .withNewMetadata()
+            .withName("test-deployment")
+            .endMetadata()
+            .build()
+        val configMap = ConfigMapBuilder()
+            .withNewMetadata()
+            .withName("test-configmap")
+            .endMetadata()
+            .build()
+
+        val createdResourceSet = deployAndGetResource(deployment, configMap)
+        val allResources = createdResourceSet.getResourceSet(server.client)
+        assertEquals(2, allResources.size)
+        createdResourceSet.files = listOf(allResources.first().first) // only select first file from ConfigMa
+        val resources = createdResourceSet.getResourceSet(server.client)
+        assertEquals(1, resources.size)
+        assertTrue(resources.toList().first().second is Deployment)
+    }
+
+    @Test
+    fun testFileNotExist() {
+        val resource = DeploymentBuilder()
+            .withNewSpec()
+            .endSpec()
+            .withNewMetadata()
+            .withName("test-deployment")
+            .endMetadata()
+            .build()
+
+        val resourceSet = deployAndGetResource(resource)
+        resourceSet.files = listOf("non-existing-file.yaml")
+        assertThrows<DeploymentFailedException> {
+            resourceSet.getResourceSet(server.client)
+        }
+    }
+
+    @Test
+    fun testConfigMapNotExist() {
+        val resourceSet = ConfigMapResourceSet()
+        resourceSet.name = "test-configmap1"
+        assertThrows<DeploymentFailedException> {
+            resourceSet.getResourceSet(server.client)
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/benchmark/ErrorChannelMessage.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ErrorChannelMessage.kt
similarity index 94%
rename from theodolite/src/test/kotlin/theodolite/benchmark/ErrorChannelMessage.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ErrorChannelMessage.kt
index df57a2529653a39ccbde14b4a91d30352224457e..4181b7cbb90fd0c6bd2db78753560092d7ea60ca 100644
--- a/theodolite/src/test/kotlin/theodolite/benchmark/ErrorChannelMessage.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ErrorChannelMessage.kt
@@ -1,4 +1,4 @@
-package theodolite.benchmark
+package rocks.theodolite.kubernetes
 
 import io.fabric8.mockwebserver.internal.WebSocketMessage
 import java.nio.charset.StandardCharsets
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/FileSystemResourceSetTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/FileSystemResourceSetTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..1c5f32159713e7ace6857caf0f97b43c90cb36e0
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/FileSystemResourceSetTest.kt
@@ -0,0 +1,168 @@
+package rocks.theodolite.kubernetes
+
+import io.fabric8.kubernetes.api.model.*
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.fabric8.kubernetes.api.model.apps.StatefulSet
+import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer
+import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.kubernetes.client.KubernetesTestServer
+import io.quarkus.test.kubernetes.client.WithKubernetesTestServer
+import org.junit.jupiter.api.*
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.io.TempDir
+import registerResource
+import rocks.theodolite.kubernetes.model.crd.BenchmarkCRD
+import rocks.theodolite.kubernetes.model.crd.ExecutionCRD
+import java.io.FileInputStream
+import java.nio.file.Files
+import java.nio.file.Path
+
+@QuarkusTest
+@WithKubernetesTestServer
+class FileSystemResourceSetTest {
+
+    @KubernetesTestServer
+    private lateinit var server: KubernetesServer
+
+    @TempDir
+    @JvmField
+    final var tempDir: Path? = null
+
+    @BeforeEach
+    fun setUp() {
+        server.before()
+        this.server.client
+            .apiextensions().v1()
+            .customResourceDefinitions()
+            .load(FileInputStream("crd/crd-execution.yaml"))
+            .create()
+        this.server.client
+            .apiextensions().v1()
+            .customResourceDefinitions()
+            .load(FileInputStream("crd/crd-benchmark.yaml"))
+            .create()
+
+        // Apparently we need create CRD clients once
+        this.server.client.resources(ExecutionCRD::class.java)
+        this.server.client.resources(BenchmarkCRD::class.java)
+    }
+
+    @AfterEach
+    fun tearDown() {
+        server.after()
+    }
+
+    private fun copyTestResourceFile(fileName: String, tempDir: Path) {
+        val stream = javaClass.getResourceAsStream("/k8s-resource-files/$fileName")
+            ?: throw IllegalArgumentException("File does not exist")
+        val target = tempDir.resolve(fileName)
+        Files.copy(stream, target)
+    }
+
+    @Test
+    fun testLoadDeployment(@TempDir tempDir: Path) {
+        copyTestResourceFile("test-deployment.yaml", tempDir)
+
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = tempDir.toString()
+        resourceSet.files = listOf("test-deployment.yaml")
+        assertEquals(1, resourceSet.getResourceSet(server.client).size)
+        assertTrue(resourceSet.getResourceSet(server.client).toList().first().second is Deployment)
+    }
+
+    @Test
+    fun testLoadService(@TempDir tempDir: Path) {
+        copyTestResourceFile("test-service.yaml", tempDir)
+
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = tempDir.toString()
+        resourceSet.files = listOf("test-service.yaml")
+        assertEquals(1, resourceSet.getResourceSet(server.client).size)
+        assertTrue(resourceSet.getResourceSet(server.client).toList().first().second is Service)
+    }
+
+    @Test
+    fun testLoadStatefulSet(@TempDir tempDir: Path) {
+        copyTestResourceFile("test-statefulset.yaml", tempDir)
+
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = tempDir.toString()
+        resourceSet.files = listOf("test-statefulset.yaml")
+        assertEquals(1, resourceSet.getResourceSet(server.client).size)
+        assertTrue(resourceSet.getResourceSet(server.client).toList().first().second is StatefulSet)
+    }
+
+    @Test
+    fun testLoadConfigMap(@TempDir tempDir: Path) {
+        copyTestResourceFile("test-configmap.yaml", tempDir)
+
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = tempDir.toString()
+        resourceSet.files = listOf("test-configmap.yaml")
+        assertEquals(1, resourceSet.getResourceSet(server.client).size)
+        assertTrue(resourceSet.getResourceSet(server.client).toList().first().second is ConfigMap)
+    }
+
+    @Test
+    fun testLoadServiceMonitor(@TempDir tempDir: Path) {
+        val serviceMonitorContext = ResourceDefinitionContext.Builder()
+            .withGroup("monitoring.coreos.com")
+            .withKind("ServiceMonitor")
+            .withPlural("servicemonitors")
+            .withNamespaced(true)
+            .withVersion("v1")
+            .build()
+        server.registerResource(serviceMonitorContext)
+
+        copyTestResourceFile("test-service-monitor.yaml", tempDir)
+
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = tempDir.toString()
+        resourceSet.files = listOf("test-service-monitor.yaml")
+        assertEquals(1, resourceSet.getResourceSet(server.client).size)
+        assertTrue(resourceSet.getResourceSet(server.client).toList().first().second is GenericKubernetesResource)
+    }
+
+    @Test
+    fun testLoadBenchmark(@TempDir tempDir: Path) {
+        copyTestResourceFile("test-benchmark.yaml", tempDir)
+
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = tempDir.toString()
+        resourceSet.files = listOf("test-benchmark.yaml")
+        assertEquals(1, resourceSet.getResourceSet(server.client).size)
+        assertTrue(resourceSet.getResourceSet(server.client).toList().first().second is BenchmarkCRD)
+    }
+
+    @Test
+    fun testLoadExecution(@TempDir tempDir: Path) {
+        copyTestResourceFile("test-execution.yaml", tempDir)
+
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = tempDir.toString()
+        resourceSet.files = listOf("test-execution.yaml")
+        assertEquals(1, resourceSet.getResourceSet(server.client).size)
+        assertTrue(resourceSet.getResourceSet(server.client).toList().first().second is ExecutionCRD)
+    }
+
+    @Test
+    fun testFilesNotSet(@TempDir tempDir: Path) {
+        copyTestResourceFile("test-deployment.yaml", tempDir)
+        copyTestResourceFile("test-service.yaml", tempDir)
+
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = tempDir.toString()
+        assertEquals(2, resourceSet.getResourceSet(server.client).size)
+    }
+
+    @Test
+    fun testWrongPath(@TempDir tempDir: Path) {
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = "/not/existing/path"
+        assertThrows<DeploymentFailedException> {
+            resourceSet.getResourceSet(server.client)
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/K8sManagerTest.kt
similarity index 68%
rename from theodolite/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/K8sManagerTest.kt
index ffc3f2f2b8083ab8b8170fa77c19de3a6ef387e7..90dd01626a7c18e0b6f8d6018aae54297e758464 100644
--- a/theodolite/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/K8sManagerTest.kt
@@ -1,32 +1,31 @@
-package theodolite.k8s
+package rocks.theodolite.kubernetes
 
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties
 import io.fabric8.kubernetes.api.model.*
 import io.fabric8.kubernetes.api.model.apps.Deployment
 import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder
 import io.fabric8.kubernetes.api.model.apps.StatefulSet
 import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder
+import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext
 import io.fabric8.kubernetes.client.server.mock.KubernetesServer
 import io.quarkus.test.junit.QuarkusTest
-import org.json.JSONObject
-import org.junit.jupiter.api.AfterEach
+import io.quarkus.test.kubernetes.client.KubernetesTestServer
+import io.quarkus.test.kubernetes.client.WithKubernetesTestServer
 import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.DisplayName
 import org.junit.jupiter.api.Test
-import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
+import registerResource
+
 
 @QuarkusTest
-@JsonIgnoreProperties(ignoreUnknown = true)
-class K8sManagerTest {
-    @JsonIgnoreProperties(ignoreUnknown = true)
-    private final val server = KubernetesServer(false, true)
-    private final val testResourcePath = "./src/test/resources/k8s-resource-files/"
+@WithKubernetesTestServer
+internal class K8sManagerTest {
+
+    @KubernetesTestServer
+    private lateinit var server: KubernetesServer
 
     private final val resourceName = "test-resource"
     private final val metadata: ObjectMeta = ObjectMetaBuilder().withName(resourceName).build()
 
-
     val defaultDeployment: Deployment = DeploymentBuilder()
         .withMetadata(metadata)
         .withNewSpec()
@@ -53,18 +52,6 @@ class K8sManagerTest {
         .withMetadata(metadata)
         .build()
 
-    @BeforeEach
-    fun setUp() {
-        server.before()
-
-    }
-
-    @AfterEach
-    fun tearDown() {
-        server.after()
-
-    }
-
     @Test
     @DisplayName("Test handling of Deployments")
     fun handleDeploymentTest() {
@@ -121,32 +108,29 @@ class K8sManagerTest {
     @Test
     @DisplayName("Test handling of custom resources")
     fun handleCustomResourcesTest() {
-        val manager = K8sManager(server.client)
-        val servicemonitor = K8sResourceLoaderFromFile(server.client)
-            .loadK8sResource("ServiceMonitor", testResourcePath + "test-service-monitor.yaml")
+        val serviceMonitorContext = ResourceDefinitionContext.Builder()
+            .withGroup("monitoring.coreos.com")
+            .withKind("ServiceMonitor")
+            .withPlural("servicemonitors")
+            .withNamespaced(true)
+            .withVersion("v1")
+            .build()
+        server.registerResource(serviceMonitorContext)
 
-        val serviceMonitorContext = K8sContextFactory().create(
-            api = "v1",
-            scope = "Namespaced",
-            group = "monitoring.coreos.com",
-            plural = "servicemonitors"
-        )
-        manager.deploy(servicemonitor)
+        val manager = K8sManager(server.client)
 
-        var serviceMonitors = JSONObject(server.client.customResource(serviceMonitorContext).list())
-            .getJSONArray("items")
+        val serviceMonitorStream = javaClass.getResourceAsStream("/k8s-resource-files/test-service-monitor.yaml")
+        val serviceMonitor = server.client.load(serviceMonitorStream).get()[0]
 
-        assertEquals(1, serviceMonitors.length())
-        assertEquals(
-            "test-service-monitor",
-            serviceMonitors.getJSONObject(0).getJSONObject("metadata").getString("name")
-        )
+        manager.deploy(serviceMonitor)
 
-        manager.remove(servicemonitor)
+        val serviceMonitorsDeployed = server.client.genericKubernetesResources(serviceMonitorContext).list()
+        assertEquals(1, serviceMonitorsDeployed.items.size)
+        assertEquals("test-service-monitor", serviceMonitorsDeployed.items[0].metadata.name)
 
-        serviceMonitors = JSONObject(server.client.customResource(serviceMonitorContext).list())
-            .getJSONArray("items")
+        manager.remove(serviceMonitor)
 
-        assertEquals(0, serviceMonitors.length())
+        val serviceMonitorsDeleted = server.client.genericKubernetesResources(serviceMonitorContext).list()
+        assertEquals(0, serviceMonitorsDeleted.items.size)
     }
 }
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ResourceSetsTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ResourceSetsTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f0a6c120ca6c3397e8d41cd9f42b536b3e053caf
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ResourceSetsTest.kt
@@ -0,0 +1,132 @@
+package rocks.theodolite.kubernetes
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
+import io.fabric8.kubernetes.api.model.ConfigMap
+import io.fabric8.kubernetes.api.model.ConfigMapBuilder
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer
+import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.kubernetes.client.KubernetesTestServer
+import io.quarkus.test.kubernetes.client.WithKubernetesTestServer
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertThrows
+import org.junit.jupiter.api.io.TempDir
+import java.nio.file.Files
+import java.nio.file.Path
+
+@QuarkusTest
+@WithKubernetesTestServer
+internal class ResourceSetsTest {
+
+    @KubernetesTestServer
+    private lateinit var server: KubernetesServer
+
+    @TempDir
+    @JvmField
+    final var tempDir: Path? = null
+
+    private val objectMapper: ObjectMapper = ObjectMapper(YAMLFactory())
+
+    @BeforeEach
+    fun setUp() {
+        server.before()
+    }
+
+    @AfterEach
+    fun tearDown() {
+        server.after()
+    }
+
+    private fun deployAndGetResource(vararg resources: HasMetadata): ConfigMapResourceSet {
+        val configMap = ConfigMapBuilder()
+            .withNewMetadata().withName(resources[0].metadata.name).endMetadata()
+            .let {
+                resources.foldIndexed(it) { i, b, r ->
+                    b.addToData("resource_$i.yaml", objectMapper.writeValueAsString(r))
+                }
+            }
+            .build()
+
+        server.client.configMaps().createOrReplace(configMap)
+
+        val resourceSet = ConfigMapResourceSet()
+        resourceSet.name = resources[0].metadata.name
+
+        return resourceSet
+    }
+
+    private fun copyTestResourceFile(fileName: String, tempDir: Path) {
+        val stream = javaClass.getResourceAsStream("/k8s-resource-files/$fileName")
+            ?: throw IllegalArgumentException("File does not exist")
+        val target = tempDir.resolve(fileName)
+        Files.copy(stream, target)
+    }
+
+    @Test
+    fun testLoadConfigMap() {
+        val resource = ConfigMapBuilder()
+            .withNewMetadata()
+            .withName("test-configmap")
+            .endMetadata()
+            .build()
+        deployAndGetResource(resource)
+
+        val yamlString =
+            """
+            configMap:    
+                name: test-configmap
+                files:
+            """
+
+        val resourcesSet: ResourceSets = objectMapper.readValue(yamlString, ResourceSets::class.java)
+        assertTrue(resourcesSet.fileSystem == null)
+        assertTrue(resourcesSet.configMap != null)
+
+        val configMap = resourcesSet.loadResourceSet(server.client)
+        assertEquals(1, configMap.size)
+        assertTrue(configMap.toList().first().second is ConfigMap)
+        assertTrue(configMap.toList().first().second.toString().contains(other = resource.metadata.name))
+
+        assertEquals(configMap.elementAt(0).second, resource)
+    }
+
+    @Test
+    fun testLoadFileSystem(@TempDir tempDir: Path) {
+        copyTestResourceFile("test-deployment.yaml", tempDir)
+
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = tempDir.toString()
+        resourceSet.files = listOf("test-deployment.yaml")
+        assertEquals(1, resourceSet.getResourceSet(server.client).size)
+
+        val yamlString =
+            """
+            fileSystem:    
+                path: ${resourceSet.path}
+                files:
+                    - test-deployment.yaml
+            """
+
+        val resourcesSet: ResourceSets = objectMapper.readValue(yamlString, ResourceSets::class.java)
+        assertTrue(resourcesSet.fileSystem != null)
+        assertTrue(resourcesSet.configMap == null)
+
+        val fileSystem = resourcesSet.loadResourceSet(server.client)
+        assertEquals(fileSystem.size, 1)
+        assertTrue(fileSystem.elementAt(0).second is HasMetadata)
+    }
+
+    @Test
+    fun testEmptyResourceSets() {
+        val resourceSet = ResourceSets()
+
+        assertThrows<DeploymentFailedException> {
+            resourceSet.loadResourceSet(server.client)
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/TestBenchmarkDeployment.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestBenchmarkDeployment.kt
similarity index 56%
rename from theodolite/src/test/kotlin/theodolite/TestBenchmarkDeployment.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestBenchmarkDeployment.kt
index 68b08c294128368ee1b65549aa85c877bd4bf313..92bc2fd26a8c5e9d77b0729731b3e65833b3dd08 100644
--- a/theodolite/src/test/kotlin/theodolite/TestBenchmarkDeployment.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestBenchmarkDeployment.kt
@@ -1,6 +1,6 @@
-package theodolite
+package rocks.theodolite.kubernetes
 
-import theodolite.benchmark.BenchmarkDeployment
+import rocks.theodolite.kubernetes.BenchmarkDeployment
 
 class TestBenchmarkDeployment : BenchmarkDeployment {
     override fun setup() {}
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestBenchmarkDeploymentBuilder.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestBenchmarkDeploymentBuilder.kt
new file mode 100644
index 0000000000000000000000000000000000000000..cc7c9d6ae9a5fe158f7ba9243f23442acde001ee
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestBenchmarkDeploymentBuilder.kt
@@ -0,0 +1,21 @@
+package rocks.theodolite.kubernetes
+
+
+import rocks.theodolite.kubernetes.util.ConfigurationOverride
+import rocks.theodolite.kubernetes.patcher.PatcherDefinition
+
+class TestBenchmarkDeploymentBuilder(): BenchmarkDeploymentBuilder {
+
+    override fun buildDeployment(
+            load: Int,
+            loadPatcherDefinitions: List<PatcherDefinition>,
+            resource: Int,
+            resourcePatcherDefinitions: List<PatcherDefinition>,
+            configurationOverrides: List<ConfigurationOverride?>,
+            loadGenerationDelay: Long,
+            afterTeardownDelay: Long,
+            waitForResourcesEnabled: Boolean
+    ): BenchmarkDeployment {
+        return TestBenchmarkDeployment()
+    }
+}
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestExperimentRunnerImpl.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestExperimentRunnerImpl.kt
new file mode 100644
index 0000000000000000000000000000000000000000..896beed83e0c9436c3aadc83b1e395df06b1f5b2
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestExperimentRunnerImpl.kt
@@ -0,0 +1,24 @@
+package rocks.theodolite.kubernetes
+
+import rocks.theodolite.core.Results
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark.Slo
+import rocks.theodolite.core.ExperimentRunner
+
+class TestExperimentRunnerImpl(
+        results: Results,
+        private val mockResults: Array<Array<Boolean>>,
+        private val benchmarkDeploymentBuilder: TestBenchmarkDeploymentBuilder,
+        private val slo: List<Slo>,
+        private val executionId: Int,
+        private val loadGenerationDelay: Long,
+        private val afterTeardownDelay: Long
+) : ExperimentRunner(
+        results
+) {
+
+    override fun runExperiment(load: Int, resource: Int): Boolean {
+        val result = this.mockResults[load][resource]
+        this.results.setResult(Pair(load, resource), result)
+        return result
+    }
+}
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkCRDummy.kt
similarity index 75%
rename from theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkCRDummy.kt
index cbddbfbfc5d6f838677c6d04b0a0c79f59d8bc66..2bd52d55bb3acd3e37d53d22a1a434d53c1fff95 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkCRDummy.kt
@@ -1,9 +1,6 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.model.crd
 
-import theodolite.benchmark.KubernetesBenchmark
-import theodolite.benchmark.Resources
-import theodolite.model.crd.BenchmarkCRD
-import theodolite.util.KafkaConfig
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark
 
 class BenchmarkCRDummy(name: String) {
 
@@ -20,15 +17,16 @@ class BenchmarkCRDummy(name: String) {
         kafkaConfig.bootstrapServer = ""
         kafkaConfig.topics = emptyList()
 
+
         benchmarkCR.spec = benchmark
         benchmarkCR.metadata.name = name
         benchmarkCR.kind = "Benchmark"
         benchmarkCR.apiVersion = "v1"
+        benchmark.waitForResourcesEnabled = false
 
-
-        benchmark.infrastructure = Resources()
-        benchmark.sut = Resources()
-        benchmark.loadGenerator = Resources()
+        benchmark.infrastructure = KubernetesBenchmark.Resources()
+        benchmark.sut = KubernetesBenchmark.Resources()
+        benchmark.loadGenerator = KubernetesBenchmark.Resources()
 
         benchmark.infrastructure.resources = emptyList()
         benchmark.sut.resources = emptyList()
@@ -43,6 +41,7 @@ class BenchmarkCRDummy(name: String) {
 
         benchmark.resourceTypes = emptyList()
         benchmark.loadTypes = emptyList()
+        benchmark.slos = mutableListOf()
         benchmark.kafkaConfig = kafkaConfig
         benchmark.name = benchmarkCR.metadata.name
     }
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/CRDExecutionTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/CRDExecutionTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a7de76acfe7aac9b92628e87b9911599a13ab438
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/CRDExecutionTest.kt
@@ -0,0 +1,86 @@
+package rocks.theodolite.kubernetes.model.crd
+
+import io.fabric8.kubernetes.api.model.KubernetesResourceList
+import io.fabric8.kubernetes.client.dsl.MixedOperation
+import io.fabric8.kubernetes.client.dsl.Resource
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer
+import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.kubernetes.client.KubernetesTestServer
+import io.quarkus.test.kubernetes.client.WithKubernetesTestServer
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.Assertions.*
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.mockito.kotlin.mock
+import rocks.theodolite.kubernetes.operator.ExecutionEventHandler
+import rocks.theodolite.kubernetes.operator.ExecutionStateHandler
+import rocks.theodolite.kubernetes.operator.TheodoliteController
+import rocks.theodolite.kubernetes.util.ConfigurationOverride
+import java.io.FileInputStream
+
+
+// TODO move somewhere else
+typealias ExecutionClient = MixedOperation<ExecutionCRD, KubernetesResourceList<ExecutionCRD>, Resource<ExecutionCRD>>
+
+@WithKubernetesTestServer
+@QuarkusTest
+internal class CRDExecutionTest {
+
+     @KubernetesTestServer
+     private lateinit var server: KubernetesServer
+
+     lateinit var executionClient: ExecutionClient
+
+     lateinit var controller: TheodoliteController
+
+     lateinit var stateHandler: ExecutionStateHandler
+
+     lateinit var eventHandler: ExecutionEventHandler
+
+     @BeforeEach
+     fun setUp() {
+          server.before()
+
+          this.server.client
+                  .apiextensions().v1()
+                  .customResourceDefinitions()
+                  .load(FileInputStream("crd/crd-execution.yaml"))
+                  .create()
+
+          this.executionClient = this.server.client.resources(ExecutionCRD::class.java)
+
+          this.controller = mock()
+          this.stateHandler = ExecutionStateHandler(server.client)
+          this.eventHandler = ExecutionEventHandler(this.controller, this.stateHandler)
+     }
+
+     @AfterEach
+     fun tearDown() {
+          server.after()
+     }
+
+     @Test
+     fun checkParsingCRDTest(){
+          // BenchmarkExecution from yaml
+          val execution = executionClient.load(ClassLoader.getSystemResourceAsStream("k8s-resource-files/test-execution.yaml")).create().spec
+
+          assertEquals(0, execution.executionId)
+          assertEquals("test", execution.name)
+          assertEquals("uc1-kstreams", execution.benchmark)
+          assertEquals(mutableListOf<ConfigurationOverride?>(), execution.configOverrides)
+
+          assertEquals("NumSensors", execution.loads.loadType)
+          assertEquals(listOf(25000, 50000, 75000, 100000, 125000, 150000),execution.loads.loadValues)
+
+          assertEquals("Instances", execution.resources.resourceType)
+          assertEquals(listOf(1, 2, 3, 4, 5), execution.resources.resourceValues)
+
+          assertEquals("demand", execution.execution.metric)
+          assertEquals(300, execution.execution.duration)
+          assertEquals(1, execution.execution.repetitions)
+
+          assertEquals("RestrictionSearch", execution.execution.strategy.name)
+          assertEquals("LinearSearch", execution.execution.strategy.searchStrategy)
+          assertEquals(listOf("LowerBound"), execution.execution.strategy.restrictions)
+     }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionCRDummy.kt
similarity index 78%
rename from theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionCRDummy.kt
index 9274e283b48a6fd9b30d5ce0aff3cb8b995e0ce5..871471ee941f5cf2d254fb2bd70556f161d8d4de 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionCRDummy.kt
@@ -1,9 +1,6 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.model.crd
 
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.model.crd.ExecutionCRD
-import theodolite.model.crd.ExecutionStatus
-import theodolite.model.crd.ExecutionState
+import rocks.theodolite.kubernetes.model.BenchmarkExecution
 
 class ExecutionCRDummy(name: String, benchmark: String) {
 
@@ -36,16 +33,24 @@ class ExecutionCRDummy(name: String, benchmark: String) {
         resourceDef.resourceType = ""
         resourceDef.resourceValues = emptyList()
 
+        val strat = BenchmarkExecution.Strategy()
+        strat.name = ""
+        strat.restrictions = emptyList()
+        strat.guessStrategy = ""
+        strat.searchStrategy = ""
+
+
         val exec = BenchmarkExecution.Execution()
         exec.afterTeardownDelay = 0
         exec.duration = 0
         exec.loadGenerationDelay = 0
         exec.repetitions = 1
-        exec.restrictions = emptyList()
-        exec.strategy = ""
+        exec.metric = ""
+        exec.strategy = strat
+
 
         execution.benchmark = benchmark
-        execution.load = loadType
+        execution.loads = loadType
         execution.resources = resourceDef
         execution.slos = emptyList()
         execution.execution = exec
diff --git a/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStateComparatorTest.kt
similarity index 86%
rename from theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStateComparatorTest.kt
index ae80312afd2c128f0f542306a8ffda7f3f53876b..14186ef408acd3233ce866102497bc56af1cdfda 100644
--- a/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStateComparatorTest.kt
@@ -1,10 +1,8 @@
-package theodolite.util
+package rocks.theodolite.kubernetes.model.crd
 
 import io.quarkus.test.junit.QuarkusTest
 import org.junit.jupiter.api.Assertions.assertEquals
 import org.junit.jupiter.api.Test
-import theodolite.execution.operator.ExecutionCRDummy
-import theodolite.model.crd.ExecutionState
 
 
 @QuarkusTest
diff --git a/theodolite/src/test/kotlin/theodolite/model/crd/ExecutionStatusTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStatusTest.kt
similarity index 99%
rename from theodolite/src/test/kotlin/theodolite/model/crd/ExecutionStatusTest.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStatusTest.kt
index 157bc1c03cc40375c928677189f549052e1e134d..4c9326ac2e99dd7dd9707d4db25cb2e9e360ddf9 100644
--- a/theodolite/src/test/kotlin/theodolite/model/crd/ExecutionStatusTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStatusTest.kt
@@ -1,4 +1,4 @@
-package theodolite.model.crd
+package rocks.theodolite.kubernetes.model.crd
 
 import com.fasterxml.jackson.databind.ObjectMapper
 import com.fasterxml.jackson.databind.exc.InvalidFormatException
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkStateCheckerTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateCheckerTest.kt
similarity index 85%
rename from theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkStateCheckerTest.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateCheckerTest.kt
index 528cfac8066c28bf6382fb97cddf280b3c1de622..d9009222122f99d587c5dc6522a794639a84d4e6 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkStateCheckerTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateCheckerTest.kt
@@ -1,4 +1,4 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
 import com.google.gson.Gson
 import io.fabric8.kubernetes.api.model.ConfigMapBuilder
@@ -13,8 +13,13 @@ import org.junit.jupiter.api.AfterEach
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import org.junit.jupiter.api.Assertions.*
-import theodolite.benchmark.*
-import theodolite.model.crd.BenchmarkState
+import rocks.theodolite.kubernetes.ActionSelector
+import rocks.theodolite.kubernetes.model.crd.BenchmarkState
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark
+import rocks.theodolite.kubernetes.model.crd.BenchmarkCRDummy
+import rocks.theodolite.kubernetes.ConfigMapResourceSet
+import rocks.theodolite.kubernetes.PodSelector
+import rocks.theodolite.kubernetes.ResourceSets
 
 internal class BenchmarkStateCheckerTest {
     private val server = KubernetesServer(false, false)
@@ -26,17 +31,17 @@ internal class BenchmarkStateCheckerTest {
     fun setUp() {
         server.before()
         serverCrud.before()
-        val operator = TheodoliteOperator()
+        val operator = TheodoliteOperator(serverCrud.client)
         checker = BenchmarkStateChecker(
             client = server.client,
-            benchmarkCRDClient = operator.getBenchmarkClient(server.client),
-            benchmarkStateHandler = operator.getBenchmarkStateHandler(server.client)
+            benchmarkCRDClient = operator.getBenchmarkClient(),
+            benchmarkStateHandler = operator.getBenchmarkStateHandler()
         )
 
         checkerCrud = BenchmarkStateChecker(
             client = serverCrud.client,
-            benchmarkCRDClient = operator.getBenchmarkClient(serverCrud.client),
-            benchmarkStateHandler = operator.getBenchmarkStateHandler(serverCrud.client)
+            benchmarkCRDClient = operator.getBenchmarkClient(),
+            benchmarkStateHandler = operator.getBenchmarkStateHandler()
         )
 
         val pod: Pod = PodBuilder().withNewMetadata()
@@ -162,16 +167,17 @@ internal class BenchmarkStateCheckerTest {
 
     @Test
     fun checkResources() {
-        val benchmark = BenchmarkCRDummy(
+        val benchmarkCR = BenchmarkCRDummy(
             name = "test-benchmark"
         )
-        benchmark.getCR().spec.setClient(serverCrud.client)
-        val resourceSet = Resources()
+        val benchmark = benchmarkCR.getCR().spec
+
+        val resourceSet = KubernetesBenchmark.Resources()
         resourceSet.resources = listOf(createAndDeployConfigmapResourceSet())
-        benchmark.getCR().spec.infrastructure = resourceSet
-        benchmark.getCR().spec.loadGenerator = resourceSet
-        benchmark.getCR().spec.sut = resourceSet
+        benchmark.infrastructure = resourceSet
+        benchmark.loadGenerator = resourceSet
+        benchmark.sut = resourceSet
 
-        assertEquals(BenchmarkState.READY,checkerCrud.checkResources(benchmark.getCR().spec))
+        assertEquals(BenchmarkState.READY,checkerCrud.checkResources(benchmark))
     }
 }
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ControllerTest.kt
similarity index 91%
rename from theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ControllerTest.kt
index 7d40f7e45d6aa2c93206a1bad22754fe93b0c100..3120d7420065cfe254d1ed76735ddc8b35d2bc21 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ControllerTest.kt
@@ -1,4 +1,4 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
 import com.google.gson.Gson
 import com.google.gson.GsonBuilder
@@ -10,11 +10,10 @@ import org.junit.jupiter.api.Assertions.assertEquals
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.DisplayName
 import org.junit.jupiter.api.Test
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.benchmark.KubernetesBenchmark
-import theodolite.model.crd.BenchmarkCRD
-import theodolite.model.crd.BenchmarkState
-import theodolite.model.crd.ExecutionCRD
+import rocks.theodolite.kubernetes.model.BenchmarkExecution
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark
+import rocks.theodolite.kubernetes.model.crd.*
+
 
 @QuarkusTest
 class ControllerTest {
@@ -32,11 +31,10 @@ class ControllerTest {
     @BeforeEach
     fun setUp() {
         server.before()
-        val operator = TheodoliteOperator()
+        val operator = TheodoliteOperator(server.client)
         this.controller = operator.getController(
-            client = server.client,
-            executionStateHandler = operator.getExecutionStateHandler(client = server.client),
-            benchmarkStateChecker = operator.getBenchmarkStateChecker(client = server.client)
+            executionStateHandler = operator.getExecutionStateHandler(),
+            benchmarkStateChecker = operator.getBenchmarkStateChecker()
         )
 
         // benchmark
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerTest.kt
similarity index 98%
rename from theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerTest.kt
index c08e0565375de84a228a28b6d68a0b713af97d0f..e794ae1638bd6c7f265b3b7ffb08c2494ba76a37 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerTest.kt
@@ -1,4 +1,4 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
 import io.fabric8.kubernetes.api.model.KubernetesResourceList
 import io.fabric8.kubernetes.client.dsl.MixedOperation
@@ -16,8 +16,8 @@ import org.junit.jupiter.params.ParameterizedTest
 import org.junit.jupiter.params.provider.Arguments
 import org.junit.jupiter.params.provider.MethodSource
 import org.mockito.kotlin.*
-import theodolite.model.crd.ExecutionCRD
-import theodolite.model.crd.ExecutionState
+import rocks.theodolite.kubernetes.model.crd.ExecutionCRD
+import rocks.theodolite.kubernetes.model.crd.ExecutionState
 import java.io.FileInputStream
 import java.util.stream.Stream
 
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTestWithInformer.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerTestWithInformer.kt
similarity index 98%
rename from theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTestWithInformer.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerTestWithInformer.kt
index adddc705616935e5440c1c601615ce9a065df4c4..63a669fe67c66b644b6acbabedc5d79afff8ee31 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTestWithInformer.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerTestWithInformer.kt
@@ -1,4 +1,4 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
 import io.fabric8.kubernetes.client.dsl.Resource
 import io.fabric8.kubernetes.client.server.mock.KubernetesServer
@@ -11,8 +11,8 @@ import org.junit.jupiter.params.ParameterizedTest
 import org.junit.jupiter.params.provider.Arguments
 import org.junit.jupiter.params.provider.MethodSource
 import org.mockito.kotlin.*
-import theodolite.model.crd.ExecutionCRD
-import theodolite.model.crd.ExecutionState
+import rocks.theodolite.kubernetes.model.crd.ExecutionCRD
+import rocks.theodolite.kubernetes.model.crd.ExecutionState
 import java.io.FileInputStream
 import java.util.concurrent.CountDownLatch
 import java.util.stream.Stream
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerWrapper.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerWrapper.kt
similarity index 63%
rename from theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerWrapper.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerWrapper.kt
index 5dbc515a7799dd51e6395153f13d80650587d7fa..43ff721bd0f964065243188465849354bc7f8b23 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerWrapper.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerWrapper.kt
@@ -1,13 +1,14 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
 import io.fabric8.kubernetes.client.informers.ResourceEventHandler
-import theodolite.model.crd.ExecutionCRD
+import rocks.theodolite.kubernetes.operator.ExecutionEventHandler
+import rocks.theodolite.kubernetes.model.crd.ExecutionCRD
 
 class ExecutionEventHandlerWrapper(
-    private val executionEventHandler: ExecutionEventHandler,
-    private val afterOnAddCallback: () -> Unit,
-    private val afterOnUpdateCallback: () -> Unit,
-    private val afterOnDeleteCallback: () -> Unit
+        private val executionEventHandler: ExecutionEventHandler,
+        private val afterOnAddCallback: () -> Unit,
+        private val afterOnUpdateCallback: () -> Unit,
+        private val afterOnDeleteCallback: () -> Unit
 ) : ResourceEventHandler<ExecutionCRD> {
 
     override fun onAdd(execution: ExecutionCRD) {
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/StateHandlerTest.kt
similarity index 80%
rename from theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/StateHandlerTest.kt
index 138f79eadc6bdee17e62cc7a961eb7de539fa3df..ebef641d1e0a699ab5e220b0846be654fbefc672 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/StateHandlerTest.kt
@@ -1,4 +1,4 @@
-package theodolite.execution.operator
+package rocks.theodolite.kubernetes.operator
 
 import io.fabric8.kubernetes.client.server.mock.KubernetesServer
 import io.quarkus.test.junit.QuarkusTest
@@ -10,15 +10,13 @@ import org.junit.jupiter.api.Assertions.assertTrue
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.DisplayName
 import org.junit.jupiter.api.Test
-import theodolite.k8s.K8sManager
-import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
-import theodolite.model.crd.ExecutionState
-import java.time.Duration
+import rocks.theodolite.kubernetes.K8sManager
+import rocks.theodolite.kubernetes.model.crd.ExecutionCRD
+import rocks.theodolite.kubernetes.model.crd.ExecutionState
 
 @QuarkusTest
 @WithKubernetesTestServer
 class StateHandlerTest {
-    private val testResourcePath = "./src/test/resources/k8s-resource-files/"
 
     @KubernetesTestServer
     private lateinit var server: KubernetesServer
@@ -26,8 +24,8 @@ class StateHandlerTest {
     @BeforeEach
     fun setUp() {
         server.before()
-        val executionResource = K8sResourceLoaderFromFile(server.client)
-            .loadK8sResource("Execution", testResourcePath + "test-execution.yaml")
+        val executionStream = javaClass.getResourceAsStream("/k8s-resource-files/test-execution.yaml")
+        val executionResource = server.client.resources(ExecutionCRD::class.java).load(executionStream).get()
 
         K8sManager(server.client).deploy(executionResource)
     }
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/AbstractPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/AbstractPatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..cb92423305fd3f724753225d95150d5198f1d306
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/AbstractPatcherTest.kt
@@ -0,0 +1,98 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.*
+import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder
+import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.Test
+
+@QuarkusTest
+abstract class AbstractPatcherTest {
+
+    lateinit var resource: List<HasMetadata>
+    lateinit var patcher: Patcher
+    lateinit var value: String
+
+    fun createDeployment(): HasMetadata {
+        return DeploymentBuilder()
+            .withNewMetadata()
+                .withName("dummy")
+            .endMetadata()
+            .withNewSpec()
+                .withNewSelector()
+                    .withMatchLabels<String, String>(mapOf("labelName" to "labelValue"))
+                .endSelector()
+                    .withNewTemplate()
+                        .withNewMetadata()
+                            .withLabels<String, String>(mapOf("labelName" to "labelValue"))
+                        .endMetadata()
+                        .withNewSpec()
+                        .withContainers(
+                                ContainerBuilder()
+                                    .withName("container")
+                                    .withImage("test-image")
+                                    .build())
+                            .addNewVolume()
+                                .withName("test-volume")
+                                .withNewConfigMap()
+                                    .withName("test-configmap")
+                                .endConfigMap()
+                            .endVolume()
+                        .endSpec()
+                .endTemplate()
+            .endSpec()
+            .build()
+    }
+
+    fun createStateFulSet(): HasMetadata {
+        return StatefulSetBuilder()
+            .withNewMetadata()
+                .withName("dummy")
+            .endMetadata()
+            .withNewSpec()
+                .withNewSelector()
+                    .withMatchLabels<String, String>(mapOf("labelName" to "labelValue"))
+                .endSelector()
+                .withNewTemplate()
+                    .withNewMetadata()
+                        .withLabels<String, String>(mapOf("labelName" to "labelValue"))
+                    .endMetadata()
+                    .withNewSpec()
+                    .addNewVolume()
+                        .withName("test-volume")
+                            .withNewConfigMap()
+                                .withName("test-configmap")
+                            .endConfigMap()
+                        .endVolume()
+                    .endSpec()
+                .endTemplate()
+            .endSpec()
+            .build()
+    }
+
+    fun createService(): HasMetadata {
+        return ServiceBuilder()
+            .withNewMetadata()
+            .withName("dummy")
+            .endMetadata()
+            .build()
+    }
+
+    fun createConfigMap(): HasMetadata {
+        return ConfigMapBuilder()
+            .withNewMetadata()
+                .withName("dummy")
+            .endMetadata()
+            .withData<String, String>(mapOf("application.properties" to "propA = valueA"))
+            .build()
+    }
+
+    fun patch() {
+        resource = patcher.patch(resource, value)
+    }
+
+    @Test
+    abstract fun validate()
+
+
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/patcher/ConfigOverrideModifierTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ConfigOverrideModifierTest.kt
similarity index 82%
rename from theodolite/src/test/kotlin/theodolite/patcher/ConfigOverrideModifierTest.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ConfigOverrideModifierTest.kt
index 1db1122e1caa5a783159ecaba849b99963e3c2a9..6172454008266c987b335999b7d8bbe67bb0fc02 100644
--- a/theodolite/src/test/kotlin/theodolite/patcher/ConfigOverrideModifierTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ConfigOverrideModifierTest.kt
@@ -1,13 +1,13 @@
-package theodolite.patcher
+package rocks.theodolite.kubernetes.patcher
 
 import io.quarkus.test.junit.QuarkusTest
 import org.junit.jupiter.api.Assertions
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.benchmark.KubernetesBenchmark
-import theodolite.execution.operator.BenchmarkCRDummy
-import theodolite.execution.operator.ExecutionCRDummy
+import rocks.theodolite.kubernetes.model.BenchmarkExecution
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark
+import rocks.theodolite.kubernetes.model.crd.BenchmarkCRDummy
+import rocks.theodolite.kubernetes.model.crd.ExecutionCRDummy
 
 @QuarkusTest
 class ConfigOverrideModifierTest {
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/DataVolumeLoadGeneratorReplicaPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/DataVolumeLoadGeneratorReplicaPatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6c9be1b9a59f963c8996e520b55e16caf24cbf6c
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/DataVolumeLoadGeneratorReplicaPatcherTest.kt
@@ -0,0 +1,28 @@
+package theodolite.patcher
+
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import rocks.theodolite.kubernetes.patcher.AbstractPatcherTest
+
+import rocks.theodolite.kubernetes.patcher.VolumesConfigMapPatcher
+
+@QuarkusTest
+internal class DataVolumeLoadGeneratorReplicaPatcherTest: AbstractPatcherTest() {
+
+    @BeforeEach
+    fun setUp() {
+        resource = listOf(createDeployment())
+        patcher = VolumesConfigMapPatcher((resource.first() as Deployment).spec.template.spec.volumes[0].configMap.name)
+        value = "new-configMapName"
+    }
+
+    @Test
+    override fun validate() {
+        patch()
+        resource.forEach {
+            assert((it as Deployment).spec.template.spec.volumes[0].configMap.name == value)
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/EnvVarPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/EnvVarPatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..83cd056ac1b56b13fb8f211a2d926f1272c9fb0e
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/EnvVarPatcherTest.kt
@@ -0,0 +1,34 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.EnvVarBuilder
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.Test
+
+import org.junit.jupiter.api.Assertions.*
+import org.junit.jupiter.api.BeforeEach
+
+@QuarkusTest
+internal class EnvVarPatcherTest : AbstractPatcherTest() {
+
+    @BeforeEach
+    fun setUp() {
+        resource = listOf(createDeployment())
+        patcher = EnvVarPatcher(variableName = "testEnv", container = "container")
+        value = "testValue"
+    }
+
+    @AfterEach
+    fun tearDown() {
+    }
+
+    @Test
+    override fun validate() {
+        patch()
+        val envVar = EnvVarBuilder().withName("testEnv").withValue("testValue").build()
+        resource.forEach {
+        assertTrue((it as Deployment).spec.template.spec.containers[0].env.contains(envVar))
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ImagePatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ImagePatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7b3f803a4e13039b7bb40aec6259f7d9a4fdbb57
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ImagePatcherTest.kt
@@ -0,0 +1,32 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+import org.junit.jupiter.api.Assertions.*
+
+@QuarkusTest
+internal class ImagePatcherTest: AbstractPatcherTest(){
+
+    @BeforeEach
+    fun setUp() {
+        resource = listOf(createDeployment())
+        patcher = ImagePatcher(container = "container")
+        value = "testValue"
+    }
+
+    @AfterEach
+    fun tearDown() {
+    }
+
+    @Test
+    override fun validate() {
+        patch()
+        resource.forEach {
+            assertTrue((it as Deployment).spec.template.spec.containers[0].image  == value)
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/LabelPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/LabelPatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..652dda47cef34a7a95e54c36cbe9af9c897b84a1
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/LabelPatcherTest.kt
@@ -0,0 +1,37 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+import org.junit.jupiter.api.Assertions.*
+
+@QuarkusTest
+internal class LabelPatcherTest: AbstractPatcherTest() {
+
+    @BeforeEach
+    fun setUp() {
+        resource = listOf(createDeployment())
+        patcher = LabelPatcher("labelName")
+        value = "labelValue"
+    }
+
+    @AfterEach
+    fun tearDown() {
+    }
+
+    @Test
+    override fun validate() {
+        patch()
+        resource.forEach {
+            assertTrue((it as Deployment).metadata.labels.containsKey("labelName"))
+            assertTrue(it.metadata.labels.get("labelName")=="labelValue")
+        }
+    }
+
+    @Test
+    fun getVariableName() {
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/MatchLabelPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/MatchLabelPatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a5711a762ab65fc39edf731c21d085d0936a5a93
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/MatchLabelPatcherTest.kt
@@ -0,0 +1,37 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+import org.junit.jupiter.api.Assertions.*
+
+@QuarkusTest
+internal class MatchLabelPatcherTest: AbstractPatcherTest() {
+
+    @BeforeEach
+    fun setUp() {
+        resource = listOf(createDeployment())
+        patcher = MatchLabelPatcher("labelName")
+        value = "labelValue"
+    }
+
+    @AfterEach
+    fun tearDown() {
+    }
+
+    @Test
+    override fun validate() {
+        patch()
+        resource.forEach {
+            assertTrue((it as Deployment).spec.selector.matchLabels.containsKey("labelName"))
+            assertTrue(it.spec.selector.matchLabels.get("labelName")=="labelValue")
+        }
+    }
+
+    @Test
+    fun getVariableName() {
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NamePatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NamePatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..cb1308cb73dc127661b2c2741fdc3e0460fcfde4
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NamePatcherTest.kt
@@ -0,0 +1,32 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+import org.junit.jupiter.api.Assertions.*
+
+@QuarkusTest
+internal class NamePatcherTest: AbstractPatcherTest() {
+
+    @BeforeEach
+    fun setUp() {
+        resource = listOf(createDeployment())
+        patcher = NamePatcher()
+        value = "newName"
+    }
+
+    @AfterEach
+    fun tearDown() {
+    }
+
+    @Test
+    override fun validate() {
+        patch()
+        resource.forEach {
+            println(it.toString())
+            assertTrue(it.toString().contains("name=$value"))
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NodeSelectorPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NodeSelectorPatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ca8f83518a5bcd96837de96b1879c0de2e9a5773
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NodeSelectorPatcherTest.kt
@@ -0,0 +1,35 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+import org.junit.jupiter.api.Assertions.*
+
+@QuarkusTest
+internal class NodeSelectorPatcherTest: AbstractPatcherTest() {
+
+    @BeforeEach
+    fun setUp() {
+        resource = listOf(createDeployment())
+        patcher = NodeSelectorPatcher("nodeName")
+        value = "nodeValue"
+
+    }
+
+    @AfterEach
+    fun tearDown() {
+    }
+
+    @Test
+    override fun validate() {
+        patch()
+        resource.forEach {
+            assertTrue((it as Deployment).spec.template.spec.nodeSelector.containsKey("nodeName"))
+            assertTrue(it.spec.template.spec.nodeSelector["nodeName"] == value)
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NumNestedGroupsLoadGeneratorReplicaPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NumNestedGroupsLoadGeneratorReplicaPatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8940e288fae79f10e5dcd728121a2dbbf0aaa180
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NumNestedGroupsLoadGeneratorReplicaPatcherTest.kt
@@ -0,0 +1,32 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+import org.junit.jupiter.api.Assertions.*
+
+@QuarkusTest
+internal class NumNestedGroupsLoadGeneratorReplicaPatcherTest : AbstractPatcherTest(){
+
+    @BeforeEach
+    fun setUp() {
+        resource = listOf(createDeployment())
+        patcher = NumNestedGroupsLoadGeneratorReplicaPatcher("10", "500")
+        value = "2"
+    }
+
+    @AfterEach
+    fun tearDown() {
+    }
+
+    @Test
+    override fun validate() {
+        patch()
+        resource.forEach {
+            assertTrue((it as Deployment).spec.replicas == 1)
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NumSensorsLoadGeneratorReplicaPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NumSensorsLoadGeneratorReplicaPatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e3bb6ffff4938bcaeb4a0db6487bd4741da75850
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NumSensorsLoadGeneratorReplicaPatcherTest.kt
@@ -0,0 +1,32 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+import org.junit.jupiter.api.Assertions.*
+
+@QuarkusTest
+internal class NumSensorsLoadGeneratorReplicaPatcherTest: AbstractPatcherTest() {
+
+    @BeforeEach
+    fun setUp() {
+        resource = listOf(createDeployment())
+        patcher = NumSensorsLoadGeneratorReplicaPatcher("10")
+        value = "2"
+    }
+
+    @AfterEach
+    fun tearDown() {
+    }
+
+    @Test
+    override fun validate() {
+        patch()
+        resource.forEach {
+            assertTrue((it as Deployment).spec.replicas == 1)
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinitionFactoryTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinitionFactoryTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..010fa1e25fb89619c8954b1bafa52c5389d0a2f3
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinitionFactoryTest.kt
@@ -0,0 +1,22 @@
+package rocks.theodolite.kubernetes.patcher
+
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+import org.junit.jupiter.api.Assertions.*
+
+internal class PatcherDefinitionFactoryTest {
+
+    @BeforeEach
+    fun setUp() {
+    }
+
+    @AfterEach
+    fun tearDown() {
+    }
+
+    @Test
+    fun createPatcherDefinition() {
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ReplicaPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ReplicaPatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..852002a07cfb756086afbc6d0573fc548f945683
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ReplicaPatcherTest.kt
@@ -0,0 +1,32 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+import org.junit.jupiter.api.Assertions.*
+
+@QuarkusTest
+internal class ReplicaPatcherTest: AbstractPatcherTest() {
+
+    @BeforeEach
+    fun setUp() {
+        resource = listOf(createDeployment())
+        patcher = ReplicaPatcher()
+        value = "5"
+    }
+
+    @AfterEach
+    fun tearDown() {
+    }
+
+    @Test
+    override fun validate() {
+        patch()
+        resource.forEach {
+            assertTrue((it as Deployment).spec.replicas == 5)
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcherTest.kt
similarity index 60%
rename from theodolite/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcherTest.kt
index b7fc2d9f1b2d5110f974b3805584baa3903d5eb1..b0af74d1e207ee10fac548f27267356711943dd0 100644
--- a/theodolite/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcherTest.kt
@@ -1,13 +1,13 @@
-package theodolite
+package rocks.theodolite.kubernetes.patcher
 
-import io.fabric8.kubernetes.api.model.apps.Deployment
-import io.fabric8.kubernetes.client.DefaultKubernetesClient
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer
 import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.kubernetes.client.KubernetesTestServer
+import io.quarkus.test.kubernetes.client.WithKubernetesTestServer
 import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Disabled
 import org.junit.jupiter.api.Test
-import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
-import theodolite.patcher.PatcherFactory
-import theodolite.util.PatcherDefinition
 
 /**
  * Resource patcher test
@@ -20,41 +20,36 @@ import theodolite.util.PatcherDefinition
  * Case 4:  In the given YAML declaration neither `Resource Request` nor `Request Limit` is defined
  */
 @QuarkusTest
+@WithKubernetesTestServer
+@Disabled
 class ResourceLimitPatcherTest {
-    val testPath = "./src/test/resources/"
-    val loader = K8sResourceLoaderFromFile(DefaultKubernetesClient().inNamespace(""))
-    val patcherFactory = PatcherFactory()
+
+    @KubernetesTestServer
+    private lateinit var server: KubernetesServer
 
     fun applyTest(fileName: String) {
         val cpuValue = "50m"
         val memValue = "3Gi"
-        val k8sResource = loader.loadK8sResource("Deployment", testPath + fileName) as Deployment
+        val k8sResource = server.client.apps().deployments().load(javaClass.getResourceAsStream(fileName)).get()
 
         val defCPU = PatcherDefinition()
-        defCPU.resource = "cpu-memory-deployment.yaml"
+        defCPU.resource = "/cpu-memory-deployment.yaml"
         defCPU.type = "ResourceLimitPatcher"
-        defCPU.properties = mutableMapOf(
+        defCPU.properties = mapOf(
             "limitedResource" to "cpu",
             "container" to "application"
         )
 
         val defMEM = PatcherDefinition()
-        defMEM.resource = "cpu-memory-deployment.yaml"
+        defMEM.resource = "/cpu-memory-deployment.yaml"
         defMEM.type = "ResourceLimitPatcher"
-        defMEM.properties = mutableMapOf(
+        defMEM.properties = mapOf(
             "limitedResource" to "memory",
             "container" to "uc-application"
         )
 
-        patcherFactory.createPatcher(
-            patcherDefinition = defCPU,
-            k8sResources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource))
-        ).patch(value = cpuValue)
-
-        patcherFactory.createPatcher(
-            patcherDefinition = defMEM,
-            k8sResources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource))
-        ).patch(value = memValue)
+        PatchHandler.patchResource(mutableMapOf(Pair("cpu-memory-deployment.yaml", listOf(k8sResource as HasMetadata))), defCPU, cpuValue)
+        PatchHandler.patchResource(mutableMapOf(Pair("cpu-memory-deployment.yaml", listOf(k8sResource as HasMetadata))), defMEM, memValue)
 
         k8sResource.spec.template.spec.containers.filter { it.name == defCPU.properties["container"]!! }
             .forEach {
@@ -66,24 +61,24 @@ class ResourceLimitPatcherTest {
     @Test
     fun testWithExistingCpuAndMemoryDeclarations() {
         // Case 1: In the given YAML declaration memory and cpu are defined
-        applyTest("cpu-memory-deployment.yaml")
+        applyTest("/cpu-memory-deployment.yaml")
     }
 
     @Test
     fun testOnlyWithExistingCpuDeclarations() {
         // Case 2:  In the given YAML declaration only cpu is defined
-        applyTest("cpu-deployment.yaml")
+        applyTest("/cpu-deployment.yaml")
     }
 
     @Test
     fun testOnlyWithExistingMemoryDeclarations() {
         //  Case 3:  In the given YAML declaration only memory is defined
-        applyTest("memory-deployment.yaml")
+        applyTest("/memory-deployment.yaml")
     }
 
     @Test
     fun testWithoutResourceDeclarations() {
         // Case 4: In the given YAML declaration neither `Resource Request` nor `Request Limit` is defined
-        applyTest("no-resources-deployment.yaml")
+        applyTest("/no-resources-deployment.yaml")
     }
 }
diff --git a/theodolite/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcherTest.kt
similarity index 60%
rename from theodolite/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt
rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcherTest.kt
index 8794d4dc2d67b8af78f4fa409c727f882922d0b8..a076e541e742e97ffa95dccff925892dd63ff17a 100644
--- a/theodolite/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcherTest.kt
@@ -1,13 +1,11 @@
-package theodolite
+package rocks.theodolite.kubernetes.patcher
 
-import io.fabric8.kubernetes.api.model.apps.Deployment
-import io.fabric8.kubernetes.client.DefaultKubernetesClient
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer
 import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.kubernetes.client.KubernetesTestServer
+import io.quarkus.test.kubernetes.client.WithKubernetesTestServer
 import io.smallrye.common.constraint.Assert.assertTrue
 import org.junit.jupiter.api.Test
-import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
-import theodolite.patcher.PatcherFactory
-import theodolite.util.PatcherDefinition
 
 /**
  * Resource patcher test
@@ -20,40 +18,35 @@ import theodolite.util.PatcherDefinition
  * Case 4:  In the given YAML declaration neither `Resource Request` nor `Request Limit` is defined
  */
 @QuarkusTest
+@WithKubernetesTestServer
 class ResourceRequestPatcherTest {
-    val testPath = "./src/test/resources/"
-    val loader = K8sResourceLoaderFromFile(DefaultKubernetesClient().inNamespace(""))
-    val patcherFactory = PatcherFactory()
+
+    @KubernetesTestServer
+    private lateinit var server: KubernetesServer
 
     fun applyTest(fileName: String) {
         val cpuValue = "50m"
         val memValue = "3Gi"
-        val k8sResource = loader.loadK8sResource("Deployment", testPath + fileName) as Deployment
+        val k8sResource = server.client.apps().deployments().load(javaClass.getResourceAsStream(fileName)).get()
 
         val defCPU = PatcherDefinition()
-        defCPU.resource = "cpu-memory-deployment.yaml"
+        defCPU.resource = "/cpu-memory-deployment.yaml"
         defCPU.type = "ResourceRequestPatcher"
-        defCPU.properties = mutableMapOf(
+        defCPU.properties = mapOf(
             "requestedResource" to "cpu",
             "container" to "application"
         )
 
         val defMEM = PatcherDefinition()
-        defMEM.resource = "cpu-memory-deployment.yaml"
+        defMEM.resource = "/cpu-memory-deployment.yaml"
         defMEM.type = "ResourceRequestPatcher"
-        defMEM.properties = mutableMapOf(
+        defMEM.properties = mapOf(
             "requestedResource" to "memory",
             "container" to "application"
         )
 
-        patcherFactory.createPatcher(
-            patcherDefinition = defCPU,
-            k8sResources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource))
-        ).patch(value = cpuValue)
-        patcherFactory.createPatcher(
-            patcherDefinition = defMEM,
-            k8sResources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource))
-        ).patch(value = memValue)
+        PatchHandler.patchResource(mutableMapOf(Pair("/cpu-memory-deployment.yaml", listOf(k8sResource))), defCPU, cpuValue)
+        PatchHandler.patchResource(mutableMapOf(Pair("/cpu-memory-deployment.yaml", listOf(k8sResource))), defMEM, memValue)
 
         k8sResource.spec.template.spec.containers.filter { it.name == defCPU.properties["container"]!! }
             .forEach {
@@ -65,24 +58,24 @@ class ResourceRequestPatcherTest {
     @Test
     fun testWithExistingCpuAndMemoryDeclarations() {
         // Case 1: In the given YAML declaration memory and cpu are defined
-        applyTest("cpu-memory-deployment.yaml")
+        applyTest("/cpu-memory-deployment.yaml")
     }
 
     @Test
     fun testOnlyWithExistingCpuDeclarations() {
         // Case 2:  In the given YAML declaration only cpu is defined
-        applyTest("cpu-deployment.yaml")
+        applyTest("/cpu-deployment.yaml")
     }
 
     @Test
     fun testOnlyWithExistingMemoryDeclarations() {
         //  Case 3:  In the given YAML declaration only memory is defined
-        applyTest("memory-deployment.yaml")
+        applyTest("/memory-deployment.yaml")
     }
 
     @Test
     fun testWithoutResourceDeclarations() {
         // Case 4: In the given YAML declaration neither `Resource Request` nor `Request Limit` is defined
-        applyTest("no-resources-deployment.yaml")
+        applyTest("/no-resources-deployment.yaml")
     }
-}
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/SchedulerNamePatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/SchedulerNamePatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2b2021ec5853af4a2ef087a21bde87fb5bdc847e
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/SchedulerNamePatcherTest.kt
@@ -0,0 +1,32 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+import org.junit.jupiter.api.Assertions.*
+
+@QuarkusTest
+internal class SchedulerNamePatcherTest : AbstractPatcherTest(){
+
+    @BeforeEach
+    fun setUp() {
+        resource = listOf(createDeployment())
+        patcher = SchedulerNamePatcher()
+        value = "testScheduler"
+    }
+
+    @AfterEach
+    fun tearDown() {
+    }
+
+    @Test
+    override fun validate() {
+        patch()
+        resource.forEach {
+            assertTrue((it as Deployment).spec.template.spec.schedulerName == value)
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/TemplateLabelPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/TemplateLabelPatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..94073b9f34d6b76d69d82e4ea40ed047a68655ff
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/TemplateLabelPatcherTest.kt
@@ -0,0 +1,30 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+import org.junit.jupiter.api.Assertions.*
+
+@QuarkusTest
+internal class TemplateLabelPatcherTest: AbstractPatcherTest() {
+
+    @BeforeEach
+    fun setUp() {
+        resource = listOf(createDeployment())
+        patcher = TemplateLabelPatcher( "labelName")
+        value = "labelValue"
+    }
+
+
+    @Test
+    override fun validate() {
+        patch()
+        resource.forEach {
+            assertTrue((it as Deployment).spec.template.metadata.labels.containsKey("labelName"))
+            assertTrue(it.spec.template.metadata.labels["labelName"] =="labelValue")
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/VolumesConfigMapPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/VolumesConfigMapPatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..db3fc812e426c0f74cf68d35a158f32a3ec0bc3f
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/VolumesConfigMapPatcherTest.kt
@@ -0,0 +1,33 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+import org.junit.jupiter.api.Assertions.*
+
+@QuarkusTest
+internal class VolumesConfigMapPatcherTest: AbstractPatcherTest() {
+
+    @BeforeEach
+    fun setUp() {
+        resource = listOf(createDeployment())
+        patcher = VolumesConfigMapPatcher("test-configmap")
+        value = "patchedVolumeName"
+    }
+
+    @AfterEach
+    fun tearDown() {
+    }
+
+    @Test
+    override fun validate() {
+        patch()
+        resource.forEach {
+            println((it as Deployment).spec.template.spec.volumes[0].configMap.name)
+            assertTrue((it as Deployment).spec.template.spec.volumes[0].configMap.name == value)
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/slo/SloFactoryTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/slo/SloFactoryTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..de9d4c60dbad069ccb1229bebb4a4751cf96d98d
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/slo/SloFactoryTest.kt
@@ -0,0 +1,69 @@
+package rocks.theodolite.kubernetes.slo
+
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.Test
+import rocks.theodolite.kubernetes.model.BenchmarkExecution
+import rocks.theodolite.kubernetes.model.KubernetesBenchmark
+
+@QuarkusTest
+internal class SloFactoryTest {
+
+    @Test
+    fun overwriteSloTest() {
+
+        val benchmark = KubernetesBenchmark()
+        val execution = BenchmarkExecution()
+
+        // Define Benchmark SLOs
+        val slo = KubernetesBenchmark.Slo()
+        slo.name="test"
+        slo.sloType="lag trend"
+        slo.prometheusUrl="test.de"
+        slo.offset=0
+
+        val benchmarkSloProperties = mutableMapOf<String, String>()
+        benchmarkSloProperties["threshold"] = "2000"
+        benchmarkSloProperties["externalSloUrl"] = "http://localhost:80/evaluate-slope"
+        benchmarkSloProperties["warmup"] = "60"
+
+        slo.properties=benchmarkSloProperties
+
+        benchmark.slos = mutableListOf(slo)
+
+
+        // Define Execution SLOs, benchmark SLO values for these properties should be overwritten
+        val sloConfig = BenchmarkExecution.SloConfiguration()
+        sloConfig.name = "test"
+
+        val executionSloProperties = mutableMapOf<String, String>()
+        // overwriting properties 'threshold' and 'warmup' and adding property 'extensionTest'
+        executionSloProperties["threshold"] = "3000"
+        executionSloProperties["warmup"] = "80"
+        executionSloProperties["extensionTest"] = "extended"
+
+        sloConfig.properties = executionSloProperties
+
+        // SLO has 'name' that isn't defined in the benchmark, therefore it will be ignored by the SloFactory
+        val sloConfig2 = BenchmarkExecution.SloConfiguration()
+        sloConfig2.name = "test2"
+        sloConfig2.properties = executionSloProperties
+
+        execution.slos = listOf(sloConfig, sloConfig2)
+
+        val sloFactory = SloFactory()
+        val combinedSlos = sloFactory.createSlos(execution,benchmark)
+
+        Assertions.assertEquals(1, combinedSlos.size)
+        Assertions.assertEquals("test", combinedSlos[0].name)
+        Assertions.assertEquals("lag trend", combinedSlos[0].sloType)
+        Assertions.assertEquals("test.de", combinedSlos[0].prometheusUrl)
+        Assertions.assertEquals(0, combinedSlos[0].offset)
+
+        Assertions.assertEquals(4, combinedSlos[0].properties.size)
+        Assertions.assertEquals("3000", combinedSlos[0].properties["threshold"])
+        Assertions.assertEquals("http://localhost:80/evaluate-slope", combinedSlos[0].properties["externalSloUrl"])
+        Assertions.assertEquals("80", combinedSlos[0].properties["warmup"])
+        Assertions.assertEquals("extended", combinedSlos[0].properties["extensionTest"])
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt b/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt
deleted file mode 100644
index 580d9e747bde687a91ffb1bce2e7c9dfb6f166a2..0000000000000000000000000000000000000000
--- a/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt
+++ /dev/null
@@ -1,117 +0,0 @@
-package theodolite
-
-import io.quarkus.test.junit.QuarkusTest
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Test
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.strategies.restriction.LowerBoundRestriction
-import theodolite.strategies.searchstrategy.BinarySearch
-import theodolite.strategies.searchstrategy.CompositeStrategy
-import theodolite.strategies.searchstrategy.LinearSearch
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-import theodolite.util.Results
-
-@QuarkusTest
-class CompositeStrategyTest {
-
-    @Test
-    fun testEnd2EndLinearSearch() {
-        val mockResults = arrayOf(
-            arrayOf(true, true, true, true, true, true, true),
-            arrayOf(false, false, true, true, true, true, true),
-            arrayOf(false, false, true, true, true, true, true),
-            arrayOf(false, false, false, true, true, true, true),
-            arrayOf(false, false, false, false, true, true, true),
-            arrayOf(false, false, false, false, false, false, true),
-            arrayOf(false, false, false, false, false, false, false)
-        )
-        val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, emptyList()) }
-        val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) }
-        val results = Results()
-        val benchmark = TestBenchmark()
-        val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo()
-        val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5)
-        val linearSearch = LinearSearch(benchmarkExecutor)
-        val lowerBoundRestriction = LowerBoundRestriction(results)
-        val strategy =
-            CompositeStrategy(benchmarkExecutor, linearSearch, setOf(lowerBoundRestriction))
-
-        val actual: ArrayList<Resource?> = ArrayList()
-        val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 3, 4, 6).map { x -> Resource(x, emptyList()) })
-        expected.add(null)
-
-        for (load in mockLoads) {
-            actual.add(strategy.findSuitableResource(load, mockResources))
-        }
-
-        assertEquals(actual, expected)
-    }
-
-    @Test
-    fun testEnd2EndBinarySearch() {
-        val mockResults = arrayOf(
-            arrayOf(true, true, true, true, true, true, true),
-            arrayOf(false, false, true, true, true, true, true),
-            arrayOf(false, false, true, true, true, true, true),
-            arrayOf(false, false, false, true, true, true, true),
-            arrayOf(false, false, false, false, true, true, true),
-            arrayOf(false, false, false, false, false, false, true),
-            arrayOf(false, false, false, false, false, false, false)
-        )
-        val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, emptyList()) }
-        val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) }
-        val results = Results()
-        val benchmark = TestBenchmark()
-        val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo()
-        val benchmarkExecutorImpl =
-            TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 0)
-        val binarySearch = BinarySearch(benchmarkExecutorImpl)
-        val lowerBoundRestriction = LowerBoundRestriction(results)
-        val strategy =
-            CompositeStrategy(benchmarkExecutorImpl, binarySearch, setOf(lowerBoundRestriction))
-
-        val actual: ArrayList<Resource?> = ArrayList()
-        val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 3, 4, 6).map { x -> Resource(x, emptyList()) })
-        expected.add(null)
-
-        for (load in mockLoads) {
-            actual.add(strategy.findSuitableResource(load, mockResources))
-        }
-
-        assertEquals(actual, expected)
-    }
-
-    @Test
-    fun testEnd2EndBinarySearch2() {
-        val mockResults = arrayOf(
-            arrayOf(true, true, true, true, true, true, true, true),
-            arrayOf(false, false, true, true, true, true, true, true),
-            arrayOf(false, false, true, true, true, true, true, true),
-            arrayOf(false, false, false, true, true, true, true, true),
-            arrayOf(false, false, false, false, true, true, true, true),
-            arrayOf(false, false, false, false, false, false, true, true),
-            arrayOf(false, false, false, false, false, false, false, true)
-        )
-        val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, emptyList()) }
-        val mockResources: List<Resource> = (0..7).map { number -> Resource(number, emptyList()) }
-        val results = Results()
-        val benchmark = TestBenchmark()
-        val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo()
-        val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 0)
-        val binarySearch = BinarySearch(benchmarkExecutor)
-        val lowerBoundRestriction = LowerBoundRestriction(results)
-        val strategy =
-            CompositeStrategy(benchmarkExecutor, binarySearch, setOf(lowerBoundRestriction))
-
-        val actual: ArrayList<Resource?> = ArrayList()
-        val expected: ArrayList<Resource?> =
-            ArrayList(listOf(0, 2, 2, 3, 4, 6, 7).map { x -> Resource(x, emptyList()) })
-
-        for (load in mockLoads) {
-            actual.add(strategy.findSuitableResource(load, mockResources))
-        }
-
-        assertEquals(actual, expected)
-    }
-}
diff --git a/theodolite/src/test/kotlin/theodolite/TestBenchmark.kt b/theodolite/src/test/kotlin/theodolite/TestBenchmark.kt
deleted file mode 100644
index b08c1a18a3013e1573e4892f01698b5e509f9609..0000000000000000000000000000000000000000
--- a/theodolite/src/test/kotlin/theodolite/TestBenchmark.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-package theodolite
-
-import theodolite.benchmark.Benchmark
-import theodolite.benchmark.BenchmarkDeployment
-import theodolite.util.ConfigurationOverride
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-
-class TestBenchmark : Benchmark {
-
-    override fun setupInfrastructure() {
-    }
-
-    override fun teardownInfrastructure() {
-    }
-
-    override fun buildDeployment(
-        load: LoadDimension,
-        res: Resource,
-        configurationOverrides: List<ConfigurationOverride?>,
-        loadGenerationDelay: Long,
-        afterTeardownDelay: Long
-    ): BenchmarkDeployment {
-        return TestBenchmarkDeployment()
-    }
-}
diff --git a/theodolite/src/test/kotlin/theodolite/TestBenchmarkExecutorImpl.kt b/theodolite/src/test/kotlin/theodolite/TestBenchmarkExecutorImpl.kt
deleted file mode 100644
index 2efddc48cb93a0870d1716c58a7018145c16e2ff..0000000000000000000000000000000000000000
--- a/theodolite/src/test/kotlin/theodolite/TestBenchmarkExecutorImpl.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-package theodolite
-
-import theodolite.benchmark.Benchmark
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.execution.BenchmarkExecutor
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-import theodolite.util.Results
-import java.time.Duration
-
-class TestBenchmarkExecutorImpl(
-    private val mockResults: Array<Array<Boolean>>,
-    benchmark: Benchmark,
-    results: Results,
-    slo: List<BenchmarkExecution.Slo>,
-    executionId: Int,
-    loadGenerationDelay: Long,
-    afterTeardownDelay: Long
-) :
-    BenchmarkExecutor(
-        benchmark,
-        results,
-        executionDuration = Duration.ofSeconds(1),
-        configurationOverrides = emptyList(),
-        slos = slo,
-        repetitions = 1,
-        executionId = executionId,
-        loadGenerationDelay = loadGenerationDelay,
-        afterTeardownDelay = afterTeardownDelay,
-        executionName = "test-execution"
-    ) {
-
-    override fun runExperiment(load: LoadDimension, res: Resource): Boolean {
-        val result = this.mockResults[load.get()][res.get()]
-        this.results.setResult(Pair(load, res), result)
-        return result
-    }
-}
diff --git a/theodolite/src/test/kotlin/theodolite/benchmark/ConfigMapResourceSetTest.kt b/theodolite/src/test/kotlin/theodolite/benchmark/ConfigMapResourceSetTest.kt
deleted file mode 100644
index bc3263aa5fd06a8a19609d9f677db51f173cf54f..0000000000000000000000000000000000000000
--- a/theodolite/src/test/kotlin/theodolite/benchmark/ConfigMapResourceSetTest.kt
+++ /dev/null
@@ -1,223 +0,0 @@
-package theodolite.benchmark
-
-import com.google.gson.Gson
-import io.fabric8.kubernetes.api.model.*
-import io.fabric8.kubernetes.api.model.apps.Deployment
-import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder
-import io.fabric8.kubernetes.api.model.apps.StatefulSet
-import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder
-import io.fabric8.kubernetes.client.server.mock.KubernetesServer
-import io.quarkus.test.junit.QuarkusTest
-import org.junit.jupiter.api.AfterEach
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Assertions.assertTrue
-import org.junit.jupiter.api.BeforeEach
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertThrows
-import theodolite.k8s.CustomResourceWrapper
-import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
-import theodolite.util.DeploymentFailedException
-
-private const val testResourcePath = "./src/test/resources/k8s-resource-files/"
-
-@QuarkusTest
-class ConfigMapResourceSetTest {
-    private val server = KubernetesServer(false, true)
-
-    @BeforeEach
-    fun setUp() {
-        server.before()
-    }
-
-    @AfterEach
-    fun tearDown() {
-        server.after()
-    }
-
-    fun deployAndGetResource(resource: String): Collection<Pair<String, KubernetesResource>> {
-        val configMap1 = ConfigMapBuilder()
-            .withNewMetadata().withName("test-configmap").endMetadata()
-            .addToData("test-resource.yaml",resource)
-            .build()
-
-        server.client.configMaps().createOrReplace(configMap1)
-
-        val resourceSet = ConfigMapResourceSet()
-        resourceSet.name = "test-configmap"
-
-        return resourceSet.getResourceSet(server.client)
-    }
-
-
-    @Test
-    fun testLoadDeployment() {
-        val resourceBuilder = DeploymentBuilder()
-        resourceBuilder.withNewSpec().endSpec()
-        resourceBuilder.withNewMetadata().endMetadata()
-        val resource = resourceBuilder.build()
-        resource.metadata.name = "test-deployment"
-
-        val createdResource = deployAndGetResource(resource = Gson().toJson(resource))
-        assertEquals(1, createdResource.size)
-        assertTrue(createdResource.toMutableSet().first().second is Deployment)
-        assertTrue(createdResource.toMutableSet().first().second.toString().contains(other = resource.metadata.name))
-    }
-
-    @Test
-    fun testLoadStateFulSet() {
-        val resourceBuilder = StatefulSetBuilder()
-        resourceBuilder.withNewSpec().endSpec()
-        resourceBuilder.withNewMetadata().endMetadata()
-        val resource = resourceBuilder.build()
-        resource.metadata.name = "test-resource"
-
-        val createdResource = deployAndGetResource(resource = Gson().toJson(resource))
-        assertEquals(1, createdResource.size)
-        assertTrue(createdResource.toMutableSet().first().second is StatefulSet)
-        assertTrue(createdResource.toMutableSet().first().second.toString().contains(other = resource.metadata.name))
-    }
-
-    @Test
-    fun testLoadService() {
-        val resourceBuilder = ServiceBuilder()
-        resourceBuilder.withNewSpec().endSpec()
-        resourceBuilder.withNewMetadata().endMetadata()
-        val resource = resourceBuilder.build()
-        resource.metadata.name = "test-resource"
-
-        val createdResource = deployAndGetResource(resource = Gson().toJson(resource))
-        assertEquals(1, createdResource.size)
-        assertTrue(createdResource.toMutableSet().first().second is Service)
-        assertTrue(createdResource.toMutableSet().first().second.toString().contains(other = resource.metadata.name))
-    }
-
-    @Test
-    fun testLoadConfigMap() {
-        val resourceBuilder = ConfigMapBuilder()
-        resourceBuilder.withNewMetadata().endMetadata()
-        val resource = resourceBuilder.build()
-        resource.metadata.name = "test-resource"
-
-        val createdResource = deployAndGetResource(resource = Gson().toJson(resource))
-        assertEquals(1, createdResource.size)
-        assertTrue(createdResource.toMutableSet().first().second is ConfigMap)
-        assertTrue(createdResource.toMutableSet().first().second.toString().contains(other = resource.metadata.name))
-    }
-
-    @Test
-    fun testLoadExecution() {
-        val loader = K8sResourceLoaderFromFile(server.client)
-        val resource = loader.loadK8sResource("Execution", testResourcePath + "test-execution.yaml") as CustomResourceWrapper
-        val createdResource = deployAndGetResource(resource = Gson().toJson(resource.crAsMap))
-
-        assertEquals(1, createdResource.size)
-        assertTrue(createdResource.toMutableSet().first().second is CustomResourceWrapper)
-
-        val loadedResource = createdResource.toMutableSet().first().second
-        if (loadedResource is CustomResourceWrapper){
-            assertTrue(loadedResource.getName() == "example-execution")
-        }
-    }
-
-    @Test
-    fun testLoadBenchmark() {
-        val loader = K8sResourceLoaderFromFile(server.client)
-        val resource = loader.loadK8sResource("Benchmark", testResourcePath + "test-benchmark.yaml") as CustomResourceWrapper
-        val createdResource = deployAndGetResource(resource = Gson().toJson(resource.crAsMap))
-
-        assertEquals(1, createdResource.size)
-        assertTrue(createdResource.toMutableSet().first().second is CustomResourceWrapper)
-
-        val loadedResource = createdResource.toMutableSet().first().second
-        if (loadedResource is CustomResourceWrapper){
-            assertTrue(loadedResource.getName() == "example-benchmark")
-        }
-    }
-
-    @Test
-    fun testLoadServiceMonitor() {
-        val loader = K8sResourceLoaderFromFile(server.client)
-        val resource = loader.loadK8sResource("ServiceMonitor", testResourcePath + "test-service-monitor.yaml") as CustomResourceWrapper
-        val createdResource = deployAndGetResource(resource = Gson().toJson(resource.crAsMap))
-
-        assertEquals(1, createdResource.size)
-        assertTrue(createdResource.toMutableSet().first().second is CustomResourceWrapper)
-
-        val loadedResource = createdResource.toMutableSet().first().second
-        if (loadedResource is CustomResourceWrapper){
-            assertTrue(loadedResource.getName() == "test-service-monitor")
-        }
-    }
-
-    @Test
-    fun testMultipleFiles(){
-        val resourceBuilder = DeploymentBuilder()
-        resourceBuilder.withNewSpec().endSpec()
-        resourceBuilder.withNewMetadata().endMetadata()
-        val resource = resourceBuilder.build()
-        resource.metadata.name = "test-deployment"
-
-        val resourceBuilder1 = ConfigMapBuilder()
-        resourceBuilder1.withNewMetadata().endMetadata()
-        val resource1 = resourceBuilder1.build()
-        resource1.metadata.name = "test-configmap"
-
-        val configMap1 = ConfigMapBuilder()
-            .withNewMetadata().withName("test-configmap").endMetadata()
-            .addToData("test-deployment.yaml",Gson().toJson(resource))
-            .addToData("test-configmap.yaml",Gson().toJson(resource1))
-            .build()
-
-        server.client.configMaps().createOrReplace(configMap1)
-
-        val resourceSet = ConfigMapResourceSet()
-        resourceSet.name = "test-configmap"
-
-        val createdResourcesSet = resourceSet.getResourceSet(server.client)
-
-        assertEquals(2,createdResourcesSet.size )
-        assert(createdResourcesSet.toMutableList()[0].second is Deployment)
-        assert(createdResourcesSet.toMutableList()[1].second is ConfigMap)
-    }
-
-    @Test
-    fun testFileIsSet(){
-        val resourceBuilder = DeploymentBuilder()
-        resourceBuilder.withNewSpec().endSpec()
-        resourceBuilder.withNewMetadata().endMetadata()
-        val resource = resourceBuilder.build()
-        resource.metadata.name = "test-deployment"
-
-        val resourceBuilder1 = ConfigMapBuilder()
-        resourceBuilder1.withNewMetadata().endMetadata()
-        val resource1 = resourceBuilder1.build()
-        resource1.metadata.name = "test-configmap"
-
-        val configMap1 = ConfigMapBuilder()
-            .withNewMetadata().withName("test-configmap").endMetadata()
-            .addToData("test-deployment.yaml",Gson().toJson(resource))
-            .addToData("test-configmap.yaml",Gson().toJson(resource1))
-            .build()
-
-        server.client.configMaps().createOrReplace(configMap1)
-
-        val resourceSet = ConfigMapResourceSet()
-        resourceSet.name = "test-configmap"
-        resourceSet.files = listOf("test-deployment.yaml")
-
-        val createdResourcesSet = resourceSet.getResourceSet(server.client)
-
-        assertEquals(1, createdResourcesSet.size )
-        assert(createdResourcesSet.toMutableSet().first().second is Deployment)
-    }
-
-
-    @Test
-    fun testConfigMapNotExist() {
-        val resourceSet = ConfigMapResourceSet()
-        resourceSet.name = "test-configmap1"
-        assertThrows<DeploymentFailedException> {
-            resourceSet.getResourceSet(server.client)
-        }
-    }
-}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/benchmark/FileSystemResourceSetTest.kt b/theodolite/src/test/kotlin/theodolite/benchmark/FileSystemResourceSetTest.kt
deleted file mode 100644
index f15685c8e0ecd67b99caabb77f68cc35a78b47f2..0000000000000000000000000000000000000000
--- a/theodolite/src/test/kotlin/theodolite/benchmark/FileSystemResourceSetTest.kt
+++ /dev/null
@@ -1,111 +0,0 @@
-package theodolite.benchmark
-
-import io.fabric8.kubernetes.api.model.ConfigMap
-import io.fabric8.kubernetes.api.model.Service
-import io.fabric8.kubernetes.api.model.apps.Deployment
-import io.fabric8.kubernetes.api.model.apps.StatefulSet
-import io.fabric8.kubernetes.client.server.mock.KubernetesServer
-import org.junit.jupiter.api.AfterEach
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Assertions.assertTrue
-import org.junit.jupiter.api.BeforeEach
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertThrows
-import theodolite.k8s.CustomResourceWrapper
-import theodolite.util.DeploymentFailedException
-
-private const val testResourcePath = "./src/test/resources/k8s-resource-files/"
-
-class FileSystemResourceSetTest {
-
-    private val server = KubernetesServer(false, true)
-
-    @BeforeEach
-    fun setUp() {
-        server.before()
-    }
-
-    @AfterEach
-    fun tearDown() {
-        server.after()
-    }
-
-    @Test
-    fun testLoadDeployment() {
-        val resourceSet = FileSystemResourceSet()
-        resourceSet.path = testResourcePath
-        resourceSet.files = listOf("test-deployment.yaml")
-        assertEquals(1,resourceSet.getResourceSet(server.client).size)
-        assertTrue(resourceSet.getResourceSet(server.client).toMutableSet().first().second is Deployment)
-    }
-
-    @Test
-    fun testLoadService() {
-        val resourceSet = FileSystemResourceSet()
-        resourceSet.path = testResourcePath
-        resourceSet.files = listOf("test-service.yaml")
-        assertEquals(1,resourceSet.getResourceSet(server.client).size)
-        assertTrue(resourceSet.getResourceSet(server.client).toMutableSet().first().second is Service)
-    }
-
-    @Test
-    fun testLoadStatefulSet() {
-        val resourceSet = FileSystemResourceSet()
-        resourceSet.path = testResourcePath
-        resourceSet.files = listOf("test-statefulset.yaml")
-        assertEquals(1,resourceSet.getResourceSet(server.client).size)
-        assertTrue(resourceSet.getResourceSet(server.client).toMutableSet().first().second is StatefulSet)
-    }
-
-    @Test
-    fun testLoadConfigMap() {
-        val resourceSet = FileSystemResourceSet()
-        resourceSet.path = testResourcePath
-        resourceSet.files = listOf("test-configmap.yaml")
-        assertEquals(1,resourceSet.getResourceSet(server.client).size)
-        assertTrue(resourceSet.getResourceSet(server.client).toMutableSet().first().second is ConfigMap)
-    }
-
-    @Test
-    fun testLoadServiceMonitor() {
-        val resourceSet = FileSystemResourceSet()
-        resourceSet.path = testResourcePath
-        resourceSet.files = listOf("test-service-monitor.yaml")
-        assertEquals(1,resourceSet.getResourceSet(server.client).size)
-        assertTrue(resourceSet.getResourceSet(server.client).toMutableSet().first().second is CustomResourceWrapper)
-    }
-
-    @Test
-    fun testLoadBenchmark() {
-        val resourceSet = FileSystemResourceSet()
-        resourceSet.path = testResourcePath
-        resourceSet.files = listOf("test-benchmark.yaml")
-        assertEquals(1,resourceSet.getResourceSet(server.client).size)
-        assertTrue(resourceSet.getResourceSet(server.client).toMutableSet().first().second is CustomResourceWrapper)
-    }
-
-    @Test
-    fun testLoadExecution() {
-        val resourceSet = FileSystemResourceSet()
-        resourceSet.path = testResourcePath
-        resourceSet.files = listOf("test-execution.yaml")
-        assertEquals(1,resourceSet.getResourceSet(server.client).size)
-        assertTrue(resourceSet.getResourceSet(server.client).toMutableSet().first().second is CustomResourceWrapper)
-    }
-
-    @Test
-    fun testFilesNotSet() {
-        val resourceSet = FileSystemResourceSet()
-        resourceSet.path = testResourcePath
-        assertEquals(9,resourceSet.getResourceSet(server.client).size)
-    }
-
-    @Test
-    fun testWrongPath() {
-        val resourceSet = FileSystemResourceSet()
-        resourceSet.path = "/abc/not-exist"
-        assertThrows<DeploymentFailedException> {
-            resourceSet.getResourceSet(server.client)
-        }
-    }
-}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/k8s/K8sResourceLoaderTest.kt b/theodolite/src/test/kotlin/theodolite/k8s/K8sResourceLoaderTest.kt
deleted file mode 100644
index 4a41dac8b27b9d4ddcfb9915f759b14ea4eaba4a..0000000000000000000000000000000000000000
--- a/theodolite/src/test/kotlin/theodolite/k8s/K8sResourceLoaderTest.kt
+++ /dev/null
@@ -1,111 +0,0 @@
-package theodolite.k8s
-
-import io.fabric8.kubernetes.api.model.ConfigMap
-import io.fabric8.kubernetes.api.model.Service
-import io.fabric8.kubernetes.api.model.apps.Deployment
-import io.fabric8.kubernetes.api.model.apps.StatefulSet
-import io.fabric8.kubernetes.client.server.mock.KubernetesServer
-import io.quarkus.test.junit.QuarkusTest
-import org.junit.jupiter.api.AfterEach
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Assertions.assertTrue
-import org.junit.jupiter.api.BeforeEach
-import org.junit.jupiter.api.DisplayName
-import org.junit.jupiter.api.Test
-import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
-
-@QuarkusTest
-class K8sResourceLoaderTest {
-    private final val server = KubernetesServer(false, true)
-    private final val testResourcePath = "./src/test/resources/k8s-resource-files/"
-
-    @BeforeEach
-    fun setUp() {
-        server.before()
-    }
-
-    @AfterEach
-    fun tearDown() {
-        server.after()
-    }
-
-    @Test
-    @DisplayName("Test loading of Deployments")
-    fun loadDeploymentTest() {
-        val loader = K8sResourceLoaderFromFile(server.client)
-        val resource = loader.loadK8sResource("Deployment", testResourcePath + "test-deployment.yaml")
-
-        assertTrue(resource is Deployment)
-        assertTrue(resource.toString().contains("name=test-deployment"))
-    }
-
-    @Test
-    @DisplayName("Test loading of StatefulSet")
-    fun loadStatefulSetTest() {
-        val loader = K8sResourceLoaderFromFile(server.client)
-        val resource = loader.loadK8sResource("StatefulSet", testResourcePath + "test-statefulset.yaml")
-
-        assertTrue(resource is StatefulSet)
-        assertTrue(resource.toString().contains("name=test-statefulset"))
-    }
-
-    @Test
-    @DisplayName("Test loading of Service")
-    fun loadServiceTest() {
-        val loader = K8sResourceLoaderFromFile(server.client)
-        val resource = loader.loadK8sResource("Service", testResourcePath + "test-service.yaml")
-
-        assertTrue(resource is Service)
-        assertTrue(resource.toString().contains("name=test-service"))
-    }
-
-    @Test
-    @DisplayName("Test loading of ConfigMap")
-    fun loadConfigMapTest() {
-        val loader = K8sResourceLoaderFromFile(server.client)
-        val resource = loader.loadK8sResource("ConfigMap", testResourcePath + "test-configmap.yaml")
-
-        assertTrue(resource is ConfigMap)
-        assertTrue(resource.toString().contains("name=test-configmap"))
-    }
-
-    @Test
-    @DisplayName("Test loading of ServiceMonitors")
-    fun loadServiceMonitorTest() {
-        val loader = K8sResourceLoaderFromFile(server.client)
-        val resource = loader.loadK8sResource("ServiceMonitor", testResourcePath + "test-service-monitor.yaml")
-
-        assertTrue(resource is CustomResourceWrapper)
-        if (resource is CustomResourceWrapper) {
-            assertEquals("test-service-monitor", resource.getName())
-
-        }
-    }
-
-    @Test
-    @DisplayName("Test loading of Executions")
-    fun loadExecutionTest() {
-        val loader = K8sResourceLoaderFromFile(server.client)
-        val resource = loader.loadK8sResource("Execution", testResourcePath + "test-execution.yaml")
-
-        assertTrue(resource is CustomResourceWrapper)
-        if (resource is CustomResourceWrapper) {
-            assertEquals("example-execution", resource.getName())
-
-        }
-    }
-
-    @Test
-    @DisplayName("Test loading of Benchmarks")
-    fun loadBenchmarkTest() {
-        val loader = K8sResourceLoaderFromFile(server.client)
-        val resource = loader.loadK8sResource("Benchmark", testResourcePath + "test-benchmark.yaml")
-
-        assertTrue(resource is CustomResourceWrapper)
-        if (resource is CustomResourceWrapper) {
-            assertEquals("example-benchmark", resource.getName())
-
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/util/ResultsTest.kt b/theodolite/src/test/kotlin/theodolite/util/ResultsTest.kt
deleted file mode 100644
index 9cfc2ae78e7a8846e3f0fa136699509145e5de22..0000000000000000000000000000000000000000
--- a/theodolite/src/test/kotlin/theodolite/util/ResultsTest.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-package theodolite.util
-
-import io.quarkus.test.junit.QuarkusTest
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Assertions.assertNotNull
-import org.junit.jupiter.api.Disabled
-import org.junit.jupiter.api.Test
-
-@QuarkusTest
-internal class ResultsTest {
-
-    @Test
-    fun testMinRequiredInstancesWhenSuccessful() {
-        val results = Results()
-        results.setResult(10000, 1, true)
-        results.setResult(10000, 2, true)
-        results.setResult(20000, 1, false)
-        results.setResult(20000, 2, true)
-
-        val minRequiredInstances = results.getMinRequiredInstances(LoadDimension(20000, emptyList()))
-
-        assertNotNull(minRequiredInstances)
-        assertEquals(2, minRequiredInstances!!.get())
-    }
-
-    @Test
-    @Disabled
-    fun testMinRequiredInstancesWhenNotSuccessful() {
-        // This test is currently not implemented this way, but might later be the desired behavior.
-        val results = Results()
-        results.setResult(10000, 1, true)
-        results.setResult(10000, 2, true)
-        results.setResult(20000, 1, false)
-        results.setResult(20000, 2, false)
-
-        val minRequiredInstances = results.getMinRequiredInstances(LoadDimension(20000, emptyList()))
-
-        assertNotNull(minRequiredInstances)
-        assertEquals(2, minRequiredInstances!!.get())
-    }
-
-    private fun Results.setResult(load: Int, resources: Int, successful: Boolean) {
-        this.setResult(
-            Pair(
-                LoadDimension(load, emptyList()),
-                Resource(resources, emptyList())
-            ),
-            successful
-        )
-    }
-
-
-    @Test
-    fun testGetMaxBenchmarkedLoadWhenAllSuccessful() {
-        val results = Results()
-        results.setResult(10000, 1, true)
-        results.setResult(10000, 2, true)
-
-        val test1 = results.getMaxBenchmarkedLoad(LoadDimension(100000, emptyList()))!!.get()
-
-        assertEquals(10000, test1)
-    }
-
-    @Test
-    fun testGetMaxBenchmarkedLoadWhenLargestNotSuccessful() {
-        val results = Results()
-        results.setResult(10000, 1, true)
-        results.setResult(10000, 2, true)
-        results.setResult(20000, 1, false)
-
-        val test2 = results.getMaxBenchmarkedLoad(LoadDimension(100000, emptyList()))!!.get()
-
-        assertEquals(20000, test2)
-    }
-}
diff --git a/theodolite/src/test/resources/k8s-resource-files/test-benchmark.yaml b/theodolite/src/test/resources/k8s-resource-files/test-benchmark.yaml
index e690aa56d74d695b0b81469023ccf82d0046cf45..ad26f6c658c72231887a8e3cd4c5dc17cc787641 100644
--- a/theodolite/src/test/resources/k8s-resource-files/test-benchmark.yaml
+++ b/theodolite/src/test/resources/k8s-resource-files/test-benchmark.yaml
@@ -3,14 +3,20 @@ kind: benchmark
 metadata:
   name: example-benchmark
 spec:
-  appResource:
-    - "uc1-kstreams-deployment.yaml"
-    - "aggregation-service.yaml"
-    - "jmx-configmap.yaml"
-    - "uc1-service-monitor.yaml"
-  loadGenResource:
-    - "uc1-load-generator-deployment.yaml"
-    - "uc1-load-generator-service.yaml"
+  waitForResourcesEnabled: false
+  sut:
+    resources:
+      - configMap:
+          name: "example-configmap"
+          files:
+            - "uc1-kstreams-deployment.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "example-configmap"
+          files:
+            - uc1-load-generator-service.yaml
+            - uc1-load-generator-deployment.yaml
   resourceTypes:
     - typeName: "Instances"
       patchers:
@@ -28,11 +34,20 @@ spec:
           resource: "uc1-load-generator-deployment.yaml"
           properties:
             loadGenMaxRecords: "15000"
+  slos:
+    - name: "lag trend"
+      sloType: "lag trend"
+      prometheusUrl: "http://prometheus-operated:9090"
+      offset: 0
+      properties:
+        threshold: 3000
+        externalSloUrl: "http://localhost:80/evaluate-slope"
+        warmup: 60 # in seconds
   kafkaConfig:
-    bootstrapServer: "theodolite-cp-kafka:9092"
+    bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092"
     topics:
       - name: "input"
         numPartitions: 40
         replicationFactor: 1
       - name: "theodolite-.*"
-        removeOnly: True
\ No newline at end of file
+        removeOnly: True
diff --git a/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml b/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml
index 1407a9952b7454053d204454841d51cfb4d7dbf4..077c4ab410e3fc78a9bb47c563c2b237b922c1ba 100644
--- a/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml
+++ b/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml
@@ -5,24 +5,26 @@ metadata:
 spec:
   name: test
   benchmark: "uc1-kstreams"
-  load:
+  loads:
     loadType: "NumSensors"
     loadValues: [25000, 50000, 75000, 100000, 125000, 150000]
   resources:
     resourceType: "Instances"
     resourceValues: [1, 2, 3, 4, 5]
   slos:
-    - sloType: "lag trend"
+    - name: "lag trend"
       threshold: 2000
       prometheusUrl: "http://prometheus-operated:9090"
       externalSloUrl: "http://localhost:80/evaluate-slope"
       offset: 0
       warmup: 60 # in seconds
   execution:
-    strategy: "LinearSearch"
+    strategy:
+      name: "RestrictionSearch"
+      restrictions:
+        - "LowerBound"
+      searchStrategy: "LinearSearch"
     duration: 300 # in seconds
     repetitions: 1
     loadGenerationDelay: 30 # in seconds
-    restrictions:
-      - "LowerBound"
   configOverrides: []
diff --git a/theodolite/src/test/resources/k8s-resource-files/test-execution-update.yaml b/theodolite/src/test/resources/k8s-resource-files/test-execution-update.yaml
index c075702da218397352f1dc1e5b283534fbb4d718..504a73fe3b325368301897cacdc922e7f6e70430 100644
--- a/theodolite/src/test/resources/k8s-resource-files/test-execution-update.yaml
+++ b/theodolite/src/test/resources/k8s-resource-files/test-execution-update.yaml
@@ -5,25 +5,23 @@ metadata:
 spec:
   name: test
   benchmark: "uc1-kstreams-update"
-  load:
+  loads:
     loadType: "NumSensors"
     loadValues: [25000, 50000, 75000, 100000, 125000, 150000]
   resources:
     resourceType: "Instances"
     resourceValues: [1, 2, 3, 4, 5]
   slos:
-    - sloType: "lag trend"
-      prometheusUrl: "http://prometheus-operated:9090"
-      offset: 0
+    - name: "lag trend"
       properties:
         threshold: 2000
-        externalSloUrl: "http://localhost:80/evaluate-slope"
-        warmup: 60 # in seconds
   execution:
-    strategy: "LinearSearch"
+    strategy:
+      name: "RestrictionSearch"
+      restrictions:
+        - "LowerBound"
+      searchStrategy: "LinearSearch"
     duration: 300 # in seconds
     repetitions: 1
     loadGenerationDelay: 30 # in seconds
-    restrictions:
-      - "LowerBound"
   configOverrides: []
diff --git a/theodolite/src/test/resources/k8s-resource-files/test-execution.yaml b/theodolite/src/test/resources/k8s-resource-files/test-execution.yaml
index e12c851da5d8a79f57b1fa59b86239c219370c0f..2bd0bfc4b3602c52fc3cc5cce9729777c21f4ac4 100644
--- a/theodolite/src/test/resources/k8s-resource-files/test-execution.yaml
+++ b/theodolite/src/test/resources/k8s-resource-files/test-execution.yaml
@@ -5,25 +5,23 @@ metadata:
 spec:
   name: test
   benchmark: "uc1-kstreams"
-  load:
+  loads:
     loadType: "NumSensors"
     loadValues: [25000, 50000, 75000, 100000, 125000, 150000]
   resources:
     resourceType: "Instances"
     resourceValues: [1, 2, 3, 4, 5]
   slos:
-    - sloType: "lag trend"
-      prometheusUrl: "http://prometheus-operated:9090"
-      offset: 0
+    - name: "lag trend"
       properties:
         threshold: 2000
-        externalSloUrl: "http://localhost:80/evaluate-slope"
-        warmup: 60 # in seconds
   execution:
-    strategy: "LinearSearch"
+    strategy:
+      name: "RestrictionSearch"
+      restrictions:
+        - "LowerBound"
+      searchStrategy: "LinearSearch"
     duration: 300 # in seconds
     repetitions: 1
     loadGenerationDelay: 30 # in seconds
-    restrictions:
-      - "LowerBound"
   configOverrides: []