diff --git a/analysis/Dockerfile b/analysis/Dockerfile
index 1e396697f34f86e578890cbb68b7a8d40a21ebf8..0c8b4639bd2c36af5fcb8e79b1c5745c2deec793 100644
--- a/analysis/Dockerfile
+++ b/analysis/Dockerfile
@@ -1,4 +1,4 @@
-FROM jupyter/base-notebook
+FROM jupyter/base-notebook:python-3.8
 
 COPY . /home/jovyan
 
diff --git a/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-hazelcastjet-deployment.yaml b/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-hazelcastjet-deployment.yaml
index 636fde2588f1a454471d1b491c83895266c0e5b9..cd2b7b293d5161bf8da69ef47ea855c46d453d8d 100644
--- a/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-hazelcastjet-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-hazelcastjet-deployment.yaml
@@ -16,6 +16,8 @@ spec:
       containers:
         - name: uc-application
           image: ghcr.io/cau-se/theodolite-uc1-hazelcastjet:latest
+          ports:
+            - containerPort: 5701
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
               value: "theodolite-kafka-kafka-bootstrap:9092"
@@ -27,7 +29,30 @@ spec:
                   fieldPath: metadata.namespace
             - name: KUBERNETES_DNS_NAME
               value: "titan-ccp-aggregation.$(KUBERNETES_NAMESPACE).svc.cluster.local"
+            - 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"
           resources:
             limits:
               memory: 4Gi
-              cpu: 1000m
\ No newline at end of file
+              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-prometheus.yml
+          ports:
+            - containerPort: 5556
+          volumeMounts:
+            - name: jmx-config
+              mountPath: /etc/jmx-aggregation
+      volumes:
+        - name: jmx-config
+          configMap:
+            name: aggregation-jmx-configmap
\ 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
index 845ce7dd55c6e5d45724ec1eeabf8789e704fe77..99453c22bd8f3239b78f88d3aabf3166a1023beb 100644
--- a/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-hazelcastjet-service.yaml
+++ b/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-hazelcastjet-service.yaml
@@ -14,3 +14,6 @@ spec:
       port: 5701
       targetPort: 5701
       protocol: TCP
+    - name: metrics
+      port: 5556
+
diff --git a/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-jmx-configmap.yaml b/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-jmx-configmap.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..714e1159325f6f35673f7d40d0b3cbb9e481097d
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-jmx-configmap.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: aggregation-jmx-configmap
+data:
+  jmx-prometheus.yml: |+
+    jmxUrl: service:jmx:rmi:///jndi/rmi://localhost:5555/jmxrmi
+    lowercaseOutputName: true
+    lowercaseOutputLabelNames: true
+    ssl: false
diff --git a/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-service-monitor.yaml b/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-service-monitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4e7e758cacb5086305efa26292ddef2afc958096
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-hazelcastjet/resources/uc1-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-hazelcastjet/uc1-hazelcastjet-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc1-hazelcastjet/uc1-hazelcastjet-benchmark-operator.yaml
index 6f7effd4228ca4b69397302361efc4d8308edf78..b90994a2f1b7335fc3752e2f2ff0eee474698191 100644
--- a/theodolite-benchmarks/definitions/uc1-hazelcastjet/uc1-hazelcastjet-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc1-hazelcastjet/uc1-hazelcastjet-benchmark-operator.yaml
@@ -14,6 +14,8 @@ spec:
           files:
           - "uc1-hazelcastjet-deployment.yaml"
           - "uc1-hazelcastjet-service.yaml"
+          - "uc1-jmx-configmap.yaml"
+          - "uc1-service-monitor.yaml"
   loadGenerator:
     resources:
       - configMap:
diff --git a/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-hazelcastjet-deployment.yaml b/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-hazelcastjet-deployment.yaml
index 0d9f7372416049afd57bb35056ac39d4d7bdd75e..3d265bcd8360c5641d80ad08b59decf3c477eeaf 100644
--- a/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-hazelcastjet-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-hazelcastjet-deployment.yaml
@@ -16,6 +16,8 @@ spec:
       containers:
         - name: uc-application
           image: ghcr.io/cau-se/theodolite-uc2-hazelcastjet:latest
+          ports:
+            - containerPort: 5701
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
               value: "theodolite-kafka-kafka-bootstrap:9092"
@@ -29,7 +31,30 @@ spec:
                   fieldPath: metadata.namespace
             - name: KUBERNETES_DNS_NAME
               value: "titan-ccp-aggregation.$(KUBERNETES_NAMESPACE).svc.cluster.local"
+            - 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"
           resources:
             limits:
               memory: 4Gi
-              cpu: 1000m
\ No newline at end of file
+              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-prometheus.yml
+          ports:
+            - containerPort: 5556
+          volumeMounts:
+            - name: jmx-config
+              mountPath: /etc/jmx-aggregation
+      volumes:
+        - name: jmx-config
+          configMap:
+            name: aggregation-jmx-configmap
diff --git a/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-hazelcastjet-service.yaml b/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-hazelcastjet-service.yaml
index 845ce7dd55c6e5d45724ec1eeabf8789e704fe77..5c3b72813e350a4f35fa91b2f7e7f5c67185ff96 100644
--- a/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-hazelcastjet-service.yaml
+++ b/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-hazelcastjet-service.yaml
@@ -14,3 +14,5 @@ spec:
       port: 5701
       targetPort: 5701
       protocol: TCP
+    - name: metrics
+      port: 5556
diff --git a/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-jmx-configmap.yaml b/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-jmx-configmap.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..714e1159325f6f35673f7d40d0b3cbb9e481097d
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-jmx-configmap.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: aggregation-jmx-configmap
+data:
+  jmx-prometheus.yml: |+
+    jmxUrl: service:jmx:rmi:///jndi/rmi://localhost:5555/jmxrmi
+    lowercaseOutputName: true
+    lowercaseOutputLabelNames: true
+    ssl: false
diff --git a/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-service-monitor.yaml b/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-service-monitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4e7e758cacb5086305efa26292ddef2afc958096
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc2-hazelcastjet/resources/uc2-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-hazelcastjet/uc2-hazelcastjet-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc2-hazelcastjet/uc2-hazelcastjet-benchmark-operator.yaml
index ad6fd7df7e00cf0f9bdc3e1f686cf982effe269b..8ce965859c43ada478fb73b2d48b986524aad750 100644
--- a/theodolite-benchmarks/definitions/uc2-hazelcastjet/uc2-hazelcastjet-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc2-hazelcastjet/uc2-hazelcastjet-benchmark-operator.yaml
@@ -14,6 +14,8 @@ spec:
           files:
             - "uc2-hazelcastjet-deployment.yaml"
             - "uc2-hazelcastjet-service.yaml"
+            - "uc2-jmx-configmap.yaml"
+            - "uc2-service-monitor.yaml"
   loadGenerator:
     resources:
       - configMap:
diff --git a/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-hazelcastjet-deployment.yaml b/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-hazelcastjet-deployment.yaml
index 248dccb83191f273f073912905896be192df8b4c..3e66eea00ea5044365ddf123f216d9332fdd1052 100644
--- a/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-hazelcastjet-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-hazelcastjet-deployment.yaml
@@ -16,6 +16,8 @@ spec:
       containers:
         - name: uc-application
           image: ghcr.io/cau-se/theodolite-uc3-hazelcastjet:latest
+          ports:
+            - containerPort: 5701
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
               value: "theodolite-kafka-kafka-bootstrap:9092"
@@ -29,7 +31,30 @@ spec:
                   fieldPath: metadata.namespace
             - name: KUBERNETES_DNS_NAME
               value: "titan-ccp-aggregation.$(KUBERNETES_NAMESPACE).svc.cluster.local"
+            - 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"
           resources:
             limits:
               memory: 4Gi
-              cpu: 1000m
\ No newline at end of file
+              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-prometheus.yml
+          ports:
+            - containerPort: 5556
+          volumeMounts:
+            - name: jmx-config
+              mountPath: /etc/jmx-aggregation
+      volumes:
+        - name: jmx-config
+          configMap:
+            name: aggregation-jmx-configmap
diff --git a/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-hazelcastjet-service.yaml b/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-hazelcastjet-service.yaml
index 845ce7dd55c6e5d45724ec1eeabf8789e704fe77..5c3b72813e350a4f35fa91b2f7e7f5c67185ff96 100644
--- a/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-hazelcastjet-service.yaml
+++ b/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-hazelcastjet-service.yaml
@@ -14,3 +14,5 @@ spec:
       port: 5701
       targetPort: 5701
       protocol: TCP
+    - name: metrics
+      port: 5556
diff --git a/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-jmx-configmap.yaml b/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-jmx-configmap.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..714e1159325f6f35673f7d40d0b3cbb9e481097d
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-jmx-configmap.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: aggregation-jmx-configmap
+data:
+  jmx-prometheus.yml: |+
+    jmxUrl: service:jmx:rmi:///jndi/rmi://localhost:5555/jmxrmi
+    lowercaseOutputName: true
+    lowercaseOutputLabelNames: true
+    ssl: false
diff --git a/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-service-monitor.yaml b/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-service-monitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4e7e758cacb5086305efa26292ddef2afc958096
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc3-hazelcastjet/resources/uc3-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-hazelcastjet/uc3-hazelcastjet-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc3-hazelcastjet/uc3-hazelcastjet-benchmark-operator.yaml
index c535de4a68452cb8531d5551586b0a0812b70e53..55ae3778495aa672003b6cb4f61f5ab616cb2ee7 100644
--- a/theodolite-benchmarks/definitions/uc3-hazelcastjet/uc3-hazelcastjet-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc3-hazelcastjet/uc3-hazelcastjet-benchmark-operator.yaml
@@ -14,6 +14,8 @@ spec:
           files:
             - "uc3-hazelcastjet-deployment.yaml"
             - "uc3-hazelcastjet-service.yaml"
+            - "uc3-jmx-configmap.yaml"
+            - "uc3-service-monitor.yaml"
   loadGenerator:
     resources:
       - configMap:
diff --git a/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-hazelcastjet-deployment.yaml b/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-hazelcastjet-deployment.yaml
index 06fabde838022e17faceef6df30fe7bfd6198e66..1cf62cba16471930df2e899702b59c243cb2c655 100644
--- a/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-hazelcastjet-deployment.yaml
+++ b/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-hazelcastjet-deployment.yaml
@@ -16,6 +16,8 @@ spec:
       containers:
         - name: uc-application
           image: ghcr.io/cau-se/theodolite-uc4-hazelcastjet:latest
+          ports:
+            - containerPort: 5701
           env:
             - name: KAFKA_BOOTSTRAP_SERVERS
               value: "theodolite-kafka-kafka-bootstrap:9092"
@@ -29,7 +31,30 @@ spec:
                   fieldPath: metadata.namespace
             - name: KUBERNETES_DNS_NAME
               value: "titan-ccp-aggregation.$(KUBERNETES_NAMESPACE).svc.cluster.local"
+            - 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"
           resources:
             limits:
               memory: 4Gi
-              cpu: 1000m
\ No newline at end of file
+              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-prometheus.yml
+          ports:
+            - containerPort: 5556
+          volumeMounts:
+            - name: jmx-config
+              mountPath: /etc/jmx-aggregation
+      volumes:
+        - name: jmx-config
+          configMap:
+            name: aggregation-jmx-configmap
diff --git a/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-hazelcastjet-service.yaml b/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-hazelcastjet-service.yaml
index 845ce7dd55c6e5d45724ec1eeabf8789e704fe77..5c3b72813e350a4f35fa91b2f7e7f5c67185ff96 100644
--- a/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-hazelcastjet-service.yaml
+++ b/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-hazelcastjet-service.yaml
@@ -14,3 +14,5 @@ spec:
       port: 5701
       targetPort: 5701
       protocol: TCP
+    - name: metrics
+      port: 5556
diff --git a/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-jmx-configmap.yaml b/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-jmx-configmap.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..714e1159325f6f35673f7d40d0b3cbb9e481097d
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-jmx-configmap.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: aggregation-jmx-configmap
+data:
+  jmx-prometheus.yml: |+
+    jmxUrl: service:jmx:rmi:///jndi/rmi://localhost:5555/jmxrmi
+    lowercaseOutputName: true
+    lowercaseOutputLabelNames: true
+    ssl: false
diff --git a/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-service-monitor.yaml b/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-service-monitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4e7e758cacb5086305efa26292ddef2afc958096
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc4-hazelcastjet/resources/uc4-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-hazelcastjet/uc4-hazelcastjet-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc4-hazelcastjet/uc4-hazelcastjet-benchmark-operator.yaml
index ab1a37da2d4356f6978772411ff835c678e5f3eb..09873c782f86da4f39181917f88ddd232252892c 100644
--- a/theodolite-benchmarks/definitions/uc4-hazelcastjet/uc4-hazelcastjet-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc4-hazelcastjet/uc4-hazelcastjet-benchmark-operator.yaml
@@ -14,6 +14,8 @@ spec:
           files:
             - "uc4-hazelcastjet-deployment.yaml"
             - "uc4-hazelcastjet-service.yaml"
+            - "uc4-jmx-configmap.yaml"
+            - "uc4-service-monitor.yaml"
   loadGenerator:
     resources:
       - configMap:
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/AbstractResourcePatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/AbstractResourcePatcher.kt
index daa873f17e4dba97b896fd455121a0e1c01e7b81..adb5c1468130069524221de25354787e045c9b9e 100644
--- a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/AbstractResourcePatcher.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/AbstractResourcePatcher.kt
@@ -28,12 +28,12 @@ abstract class AbstractResourcePatcher(
         when (resource) {
             is Deployment -> {
                 resource.spec.template.spec.containers.filter { it.name == container }.forEach {
-                    setLimits(it, value)
+                    setValues(it, value)
                 }
             }
             is StatefulSet -> {
                 resource.spec.template.spec.containers.filter { it.name == container }.forEach {
-                    setLimits(it, value)
+                    setValues(it, value)
                 }
             }
             else -> {
@@ -43,7 +43,7 @@ abstract class AbstractResourcePatcher(
         return resource
     }
 
-    private fun setLimits(container: Container, value: String) {
+    private fun setValues(container: Container, value: String) {
         val quantity = if (this.format != null || this.factor != null) {
             val amountAsInt = value.toIntOrNull()?.times(this.factor ?: 1)
             if (amountAsInt == null) {
@@ -56,8 +56,8 @@ abstract class AbstractResourcePatcher(
             Quantity(value)
         }
 
-        setLimits(container, quantity)
+        setValues(container, quantity)
     }
 
-    abstract fun setLimits(container: Container, quantity: Quantity)
+    abstract fun setValues(container: Container, quantity: Quantity)
 }
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt
index 69a2528bbcd2a39d535d77571f7ca520b8c81488..26e76ccfabbb773e45bf80fd09612473c246c5e4 100644
--- a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt
@@ -12,86 +12,76 @@ 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.
+         * @param patcher The [PatcherDefinition] for which are [Patcher] should be created.
          * @return The created [Patcher].
          * @throws IllegalArgumentException if no patcher can be created.
          */
-        fun createPatcher(
-            patcherDefinition: PatcherDefinition,
-        ): Patcher {
-
-            return try {
-                when (patcherDefinition.type) {
+        fun createPatcher(patcher: PatcherDefinition): Patcher {
+            return when (patcher.type) {
                     "ReplicaPatcher" -> ReplicaPatcher(
                     )
                     "NumNestedGroupsLoadGeneratorReplicaPatcher" -> NumNestedGroupsLoadGeneratorReplicaPatcher(
-                        loadGenMaxRecords = patcherDefinition.properties["loadGenMaxRecords"]!!,
-                        numSensors = patcherDefinition.properties["numSensors"]!!
+                        loadGenMaxRecords = patcher.properties["loadGenMaxRecords"] ?: throwInvalid(patcher),
+                        numSensors = patcher.properties["numSensors"] ?: throwInvalid(patcher)
                     )
                     "NumSensorsLoadGeneratorReplicaPatcher" -> NumSensorsLoadGeneratorReplicaPatcher(
-                        loadGenMaxRecords = patcherDefinition.properties["loadGenMaxRecords"]!!
+                        loadGenMaxRecords = patcher.properties["loadGenMaxRecords"] ?: throwInvalid(patcher)
                     )
                     "DataVolumeLoadGeneratorReplicaPatcher" -> DataVolumeLoadGeneratorReplicaPatcher(
-                        maxVolume = patcherDefinition.properties["maxVolume"]!!.toInt(),
-                        container = patcherDefinition.properties["container"]!!,
-                        variableName = patcherDefinition.properties["variableName"]!!
+                        maxVolume = (patcher.properties["maxVolume"] ?: throwInvalid(patcher)).toInt(),
+                        container = patcher.properties["container"] ?: throwInvalid(patcher),
+                        variableName = patcher.properties["variableName"] ?: throwInvalid(patcher)
                     )
                     "EnvVarPatcher" -> EnvVarPatcher(
-                        container = patcherDefinition.properties["container"]!!,
-                        variableName = patcherDefinition.properties["variableName"]!!
+                        container = patcher.properties["container"] ?: throwInvalid(patcher),
+                        variableName = patcher.properties["variableName"] ?: throwInvalid(patcher)
                     )
                     "NodeSelectorPatcher" -> NodeSelectorPatcher(
-                        variableName = patcherDefinition.properties["variableName"]!!
+                        variableName = patcher.properties["variableName"] ?: throwInvalid(patcher)
                     )
                     "ResourceLimitPatcher" -> ResourceLimitPatcher(
-                        container = patcherDefinition.properties["container"]!!,
-                        limitedResource = patcherDefinition.properties["limitedResource"]!!,
-                        format = patcherDefinition.properties["format"],
-                        factor = patcherDefinition.properties["factor"]?.toInt()
+                        container = patcher.properties["container"] ?: throwInvalid(patcher),
+                        limitedResource = patcher.properties["limitedResource"] ?: throwInvalid(patcher),
+                        format = patcher.properties["format"],
+                        factor = patcher.properties["factor"]?.toInt()
                     )
                     "ResourceRequestPatcher" -> ResourceRequestPatcher(
-                        container = patcherDefinition.properties["container"]!!,
-                        requestedResource = patcherDefinition.properties["requestedResource"]!!,
-                        format = patcherDefinition.properties["format"],
-                        factor = patcherDefinition.properties["factor"]?.toInt()
+                        container = patcher.properties["container"] ?: throwInvalid(patcher),
+                        requestedResource = patcher.properties["requestedResource"] ?: throwInvalid(patcher),
+                        format = patcher.properties["format"],
+                        factor = patcher.properties["factor"]?.toInt()
                     )
                     "SchedulerNamePatcher" -> SchedulerNamePatcher()
                     "LabelPatcher" -> LabelPatcher(
-                        variableName = patcherDefinition.properties["variableName"]!!
+                        variableName = patcher.properties["variableName"] ?: throwInvalid(patcher)
                     )
                     "MatchLabelPatcher" -> MatchLabelPatcher(
-                        variableName = patcherDefinition.properties["variableName"]!!
+                        variableName = patcher.properties["variableName"] ?: throwInvalid(patcher)
                     )
                     "TemplateLabelPatcher" -> TemplateLabelPatcher(
-                        variableName = patcherDefinition.properties["variableName"]!!
+                        variableName = patcher.properties["variableName"] ?: throwInvalid(patcher)
                     )
                     "ImagePatcher" -> ImagePatcher(
-                        container = patcherDefinition.properties["container"]!!
+                        container = patcher.properties["container"] ?: throwInvalid(patcher)
                     )
                     "ConfigMapYamlPatcher" -> ConfigMapYamlPatcher(
-                        fileName = patcherDefinition.properties["fileName"]!!,
-                        variableName = patcherDefinition.properties["variableName"]!!
+                        fileName = patcher.properties["fileName"] ?: throwInvalid(patcher),
+                        variableName = patcher.properties["variableName"] ?: throwInvalid(patcher)
                     )
                     "NamePatcher" -> NamePatcher()
                     "ServiceSelectorPatcher" -> ServiceSelectorPatcher(
-                        variableName = patcherDefinition.properties["label"]!!
+                        variableName = patcher.properties["label"] ?: throwInvalid(patcher)
                     )
                     "VolumesConfigMapPatcher" -> VolumesConfigMapPatcher(
-                        volumeName = patcherDefinition.properties["volumeName"]!!
+                        volumeName = patcher.properties["volumeName"] ?: throwInvalid(patcher)
                     )
-                    else -> throw InvalidPatcherConfigurationException("Patcher type ${patcherDefinition.type} not found.")
+                    else -> throw InvalidPatcherConfigurationException("Patcher type ${patcher.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
-                )
-            }
+        }
+
+        private fun throwInvalid(patcher: PatcherDefinition): String {
+            throw InvalidPatcherConfigurationException("Could not create patcher with type ${patcher.type}. Probably a required patcher argument was not specified.")
         }
     }
+
 }
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcher.kt
index c1ae22f00a8fde16aedef6b70ea098cbdd895dd4..b2085ed80577a11f2e3582689ad39bab3577ecdc 100644
--- a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcher.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcher.kt
@@ -24,7 +24,7 @@ class ResourceLimitPatcher(
     format = format,
     factor = factor
 ) {
-    override fun setLimits(container: Container, quantity: Quantity) {
+    override fun setValues(container: Container, quantity: Quantity) {
         when {
             container.resources == null -> {
                 val resource = ResourceRequirements()
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcher.kt
index a6b037ddeb3a1fb3d7aa2c1f2579cada81922d9a..3441ef2a9596aa781a9aa9ac2f064136f65f6a0e 100644
--- a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcher.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcher.kt
@@ -4,7 +4,6 @@ import io.fabric8.kubernetes.api.model.Container
 import io.fabric8.kubernetes.api.model.Quantity
 import io.fabric8.kubernetes.api.model.ResourceRequirements
 
-
 /**
  * The Resource request [Patcher] sets resource requests for Deployments and StatefulSets.
  *
@@ -25,7 +24,7 @@ class ResourceRequestPatcher(
     factor = factor
 ) {
 
-    override fun setLimits(container: Container, quantity: Quantity) {
+    override fun setValues(container: Container, quantity: Quantity) {
         when {
             container.resources == null -> {
                 val resource = ResourceRequirements()