This is an automated email from the ASF dual-hosted git repository.

zehnder pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to refs/heads/dev by this push:
     new 709d6e31b refactor(#2246): Refactor InfluxStore.onEvent (#2247)
709d6e31b is described below

commit 709d6e31b12251e07d39576d85d9ffed70c11200
Author: Philipp Zehnder <[email protected]>
AuthorDate: Fri Dec 1 20:15:44 2023 +0100

    refactor(#2246): Refactor InfluxStore.onEvent (#2247)
---
 streampipes-data-explorer-commons/pom.xml          |  12 +-
 .../dataexplorer/commons/TimeSeriesStore.java      |   3 +-
 .../commons/influx/InfluxClientProvider.java       |  80 +++++
 .../commons/influx/InfluxRequests.java             |  46 ---
 .../dataexplorer/commons/influx/InfluxStore.java   | 321 ++++++++---------
 .../commons/influx/PropertyHandler.java            | 193 ++++++++++
 .../commons/influx/InfluxClientProviderTest.java   | 103 ++++++
 .../commons/influx/InfluxStoreTest.java            | 395 +++++++++++++++++++++
 .../connectors/influx/adapter/InfluxDbClient.java  |   7 +-
 .../connectors/influx/sink/InfluxDbClient.java     |   7 +-
 ...lder.java => EventPropertyListTestBuilder.java} |  31 +-
 .../EventPropertyPrimitiveTestBuilder.java         |  11 +
 12 files changed, 975 insertions(+), 234 deletions(-)

diff --git a/streampipes-data-explorer-commons/pom.xml 
b/streampipes-data-explorer-commons/pom.xml
index cfcbea0c2..0377e69c6 100644
--- a/streampipes-data-explorer-commons/pom.xml
+++ b/streampipes-data-explorer-commons/pom.xml
@@ -42,13 +42,23 @@
             <artifactId>streampipes-commons</artifactId>
             <version>0.95.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.streampipes</groupId>
+            <artifactId>streampipes-test-utils</artifactId>
+            <version>0.95.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
 
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
-
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
 
         <!-- Others -->
         <dependency>
diff --git 
a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/TimeSeriesStore.java
 
b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/TimeSeriesStore.java
index 5b063fff7..31ce5cbf3 100644
--- 
a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/TimeSeriesStore.java
+++ 
b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/TimeSeriesStore.java
@@ -22,6 +22,7 @@ import org.apache.streampipes.client.api.IStreamPipesClient;
 import org.apache.streampipes.commons.environment.Environment;
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.dataexplorer.commons.image.ImageStore;
+import org.apache.streampipes.dataexplorer.commons.influx.InfluxClientProvider;
 import org.apache.streampipes.dataexplorer.commons.influx.InfluxStore;
 import org.apache.streampipes.model.datalake.DataLakeMeasure;
 import org.apache.streampipes.model.runtime.Event;
@@ -50,7 +51,7 @@ public class TimeSeriesStore {
       this.imageStore = new ImageStore(measure, environment);
     }
 
-    this.influxStore = new InfluxStore(measure, environment);
+    this.influxStore = new InfluxStore(measure, environment, new 
InfluxClientProvider());
 
   }
 
diff --git 
a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxClientProvider.java
 
b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxClientProvider.java
index b4dd11e2f..9a9e7a127 100644
--- 
a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxClientProvider.java
+++ 
b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxClientProvider.java
@@ -20,12 +20,21 @@ package org.apache.streampipes.dataexplorer.commons.influx;
 
 import org.apache.streampipes.commons.environment.Environment;
 import org.apache.streampipes.commons.environment.Environments;
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 
 import org.influxdb.InfluxDB;
 import org.influxdb.InfluxDBFactory;
+import org.influxdb.dto.Query;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 public class InfluxClientProvider {
 
+  private static final Logger LOG = 
LoggerFactory.getLogger(InfluxClientProvider.class);
+
   /**
    * Create a new InfluxDB client from environment variables
    *
@@ -58,7 +67,78 @@ public class InfluxClientProvider {
     }
   }
 
+
+  public InfluxDB getInitializedInfluxDBClient(Environment environment) {
+
+    var settings = InfluxConnectionSettings.from(environment);
+    var influxDb = InfluxClientProvider.getInfluxDBClient(settings);
+    var databaseName = settings.getDatabaseName();
+
+    // Checking, if server is available
+    var response = influxDb.ping();
+    if (response.getVersion()
+                .equalsIgnoreCase("unknown")) {
+      throw new SpRuntimeException("Could not connect to InfluxDb Server: " + 
settings.getConnectionUrl());
+    }
+
+    // Checking whether the database exists
+    if (!databaseExists(influxDb, databaseName)) {
+      LOG.info("Database '" + databaseName + "' not found. Gets created ...");
+      createDatabase(influxDb, databaseName);
+    }
+
+    // setting up the database
+    influxDb.setDatabase(databaseName);
+    var batchSize = 2000;
+    var flushDuration = 500;
+    influxDb.enableBatch(batchSize, flushDuration, TimeUnit.MILLISECONDS);
+
+    return influxDb;
+  }
+
+  /**
+   * Creates a new database with the given name
+   *
+   * @param influxDb The InfluxDB client
+   * @param dbName   The name of the database which should be created
+   */
+  public void createDatabase(
+      InfluxDB influxDb,
+      String dbName
+  ) throws SpRuntimeException {
+    if (!dbName.matches("^[a-zA-Z_]\\w*$")) {
+      throw new SpRuntimeException(
+          "Database name '" + dbName + "' not allowed. Allowed names: 
^[a-zA-Z_][a-zA-Z0-9_]*$");
+    }
+    influxDb.query(new Query("CREATE DATABASE \"" + dbName + "\"", ""));
+  }
+
+  /**
+   * Checks whether the given database exists.
+   *
+   * @param influxDb The InfluxDB client instance
+   * @param dbName The name of the database, the method should look for
+   * @return True if the database exists, false otherwise
+   */
+  public boolean databaseExists(
+      InfluxDB influxDb,
+      String dbName
+  ) {
+    var queryResult = influxDb.query(new Query("SHOW DATABASES", ""));
+    for (List<Object> a : queryResult.getResults()
+                                     .get(0)
+                                     .getSeries()
+                                     .get(0)
+                                     .getValues()) {
+      if (!a.isEmpty() && dbName.equals(a.get(0))) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   private static Environment getEnvironment() {
     return Environments.getEnvironment();
   }
+
 }
diff --git 
a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxRequests.java
 
b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxRequests.java
deleted file mode 100644
index 6522a8ee9..000000000
--- 
a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxRequests.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.dataexplorer.commons.influx;
-
-import org.influxdb.InfluxDB;
-import org.influxdb.dto.Query;
-import org.influxdb.dto.QueryResult;
-
-import java.util.List;
-
-public class InfluxRequests {
-
-  /**
-   * Checks whether the given database exists.
-   *
-   * @param influxDb The InfluxDB client instance
-   * @param dbName The name of the database, the method should look for
-   * @return True if the database exists, false otherwise
-   */
-  public static boolean databaseExists(InfluxDB influxDb,
-                                   String dbName) {
-    QueryResult queryResult = influxDb.query(new Query("SHOW DATABASES", ""));
-    for (List<Object> a : 
queryResult.getResults().get(0).getSeries().get(0).getValues()) {
-      if (a.get(0).equals(dbName)) {
-        return true;
-      }
-    }
-    return false;
-  }
-}
diff --git 
a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxStore.java
 
b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxStore.java
index 4abb33d67..0a107b1dd 100644
--- 
a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxStore.java
+++ 
b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxStore.java
@@ -20,219 +20,161 @@ package 
org.apache.streampipes.dataexplorer.commons.influx;
 
 import org.apache.streampipes.commons.environment.Environment;
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
-import 
org.apache.streampipes.dataexplorer.commons.influx.serializer.RawFieldSerializer;
 import org.apache.streampipes.model.datalake.DataLakeMeasure;
 import org.apache.streampipes.model.runtime.Event;
-import org.apache.streampipes.model.runtime.field.PrimitiveField;
+import org.apache.streampipes.model.schema.EventProperty;
 import org.apache.streampipes.model.schema.EventPropertyPrimitive;
-import org.apache.streampipes.model.schema.PropertyScope;
-import org.apache.streampipes.vocabulary.SO;
-import org.apache.streampipes.vocabulary.XSD;
 
 import org.influxdb.InfluxDB;
 import org.influxdb.dto.Point;
-import org.influxdb.dto.Query;
-import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 public class InfluxStore {
 
   private static final Logger LOG = LoggerFactory.getLogger(InfluxStore.class);
-  DataLakeMeasure measure;
-  Map<String, String> sanitizedRuntimeNames = new HashMap<>();
-  private InfluxDB influxDb = null;
 
-  private RawFieldSerializer rawFieldSerializer = new RawFieldSerializer();
+  private final DataLakeMeasure measure;
+  private final List<EventProperty> allEventProperties;
+  private final Map<String, String> sanitizedRuntimeNames = new HashMap<>();
+  private final InfluxDB influxDb;
 
-  public InfluxStore(DataLakeMeasure measure,
-                     InfluxConnectionSettings settings) {
-    this.measure = measure;
-    // store sanitized target property runtime names in local variable
-    measure.getEventSchema()
-        .getEventProperties()
-        .forEach(ep -> sanitizedRuntimeNames.put(ep.getRuntimeName(),
-            InfluxNameSanitizer.renameReservedKeywords(ep.getRuntimeName())));
+  private final PropertyHandler propertyHandler;
 
-    connect(settings);
-  }
 
-  public InfluxStore(DataLakeMeasure measure,
-                     Environment environment) throws SpRuntimeException {
-    this(measure, InfluxConnectionSettings.from(environment));
+  public InfluxStore(
+      DataLakeMeasure measure,
+      Environment environment,
+      InfluxClientProvider influxClientProvider
+  ) throws SpRuntimeException {
+    this.measure = measure;
+    storeSanitizedRuntimeNames(measure);
+    allEventProperties = getAllEventPropertiesExceptTimestamp(measure);
+    influxDb = influxClientProvider.getInitializedInfluxDBClient(environment);
+    propertyHandler = new PropertyHandler();
   }
 
   /**
-   * Connects to the InfluxDB Server, sets the database and initializes the 
batch-behaviour
+   * Takes an StreamPipes event, transforms it to an InfluxDB point and writes 
it to the InfluxDB
    *
-   * @throws SpRuntimeException If not connection can be established or if the 
database could not
-   *                            be found
+   * @param event The event which should be saved
+   * @throws SpRuntimeException If the column name (key-value of the event 
map) is not allowed
    */
-  private void connect(InfluxConnectionSettings settings) throws 
SpRuntimeException {
-    influxDb = InfluxClientProvider.getInfluxDBClient(settings);
+  public void onEvent(Event event) throws SpRuntimeException {
 
-    // Checking, if server is available
-    var response = influxDb.ping();
-    if (response.getVersion().equalsIgnoreCase("unknown")) {
-      throw new SpRuntimeException("Could not connect to InfluxDb Server: " + 
settings.getConnectionUrl());
-    }
+    validateInputEventAndLogMissingFields(event);
 
-    String databaseName = settings.getDatabaseName();
-    // Checking whether the database exists
-    if (!InfluxRequests.databaseExists(influxDb, databaseName)) {
-      LOG.info("Database '" + databaseName + "' not found. Gets created ...");
-      createDatabase(databaseName);
-    }
+    sanitizeRuntimeNamesInEvent(event);
+
+    var point = initializePointWithTimestamp(event);
 
-    // setting up the database
-    influxDb.setDatabase(databaseName);
-    var batchSize = 2000;
-    var flushDuration = 500;
-    influxDb.enableBatch(batchSize, flushDuration, TimeUnit.MILLISECONDS);
+    iterateOverallEventProperties(event, point);
+
+    influxDb.write(point.build());
+  }
+
+  private void validateInputEventAndLogMissingFields(Event event) {
+    checkEventIsNotNull(event);
+
+    logMissingFields(event);
+
+    logNullFields(event);
   }
 
   /**
-   * Creates a new database with the given name
-   *
-   * @param dbName The name of the database which should be created
+   * Logs all fields which are present in the schema, but not in the provided 
event
    */
-  private void createDatabase(String dbName) throws SpRuntimeException {
-    if (!dbName.matches("^[a-zA-Z_]\\w*$")) {
-      throw new SpRuntimeException(
-          "Database name '" + dbName + "' not allowed. Allowed names: 
^[a-zA-Z_][a-zA-Z0-9_]*$");
+  private void logMissingFields(Event event) {
+    var missingFields = getMissingProperties(allEventProperties, event);
+    if (!missingFields.isEmpty()) {
+      LOG.debug(
+          "Ignored {} fields which were present in the schema, but not in the 
provided event: {}",
+          missingFields.size(),
+          String.join(", ", missingFields)
+      );
     }
-    influxDb.query(new Query("CREATE DATABASE \"" + dbName + "\"", ""));
   }
 
+
   /**
-   * Saves an event to the connected InfluxDB database
-   *
-   * @param event The event which should be saved
-   * @throws SpRuntimeException If the column name (key-value of the event 
map) is not allowed
+   * Logs all fields that contain null values
    */
-  public void onEvent(Event event) throws SpRuntimeException {
-    var missingFields = new ArrayList<String>();
-    var nullFields = new ArrayList<String>();
-    if (event == null) {
-      throw new SpRuntimeException("event is null");
-    }
-
-    // sanitize event
-    for (var key : event.getRaw().keySet()) {
-      if (InfluxDbReservedKeywords.KEYWORD_LIST.stream().anyMatch(k -> 
k.equalsIgnoreCase(key))) {
-        event.renameFieldByRuntimeName(key, key + "_");
-      }
+  private void logNullFields(Event event) {
+    List<String> nullFields = allEventProperties
+        .stream()
+        .filter(ep -> ep instanceof EventPropertyPrimitive)
+        .filter(ep -> {
+          var runtimeName = ep.getRuntimeName();
+          var field = event.getOptionalFieldByRuntimeName(runtimeName);
+
+          return field.isPresent() && field.get()
+                                           .getAsPrimitive()
+                                           .getRawValue() == null;
+        })
+        .map(EventProperty::getRuntimeName)
+        .collect(Collectors.toList());
+
+    if (!nullFields.isEmpty()) {
+      LOG.warn("Ignored {} fields which had a value 'null': {}", 
nullFields.size(), String.join(", ", nullFields));
     }
+  }
 
-    var timestampValue = 
event.getFieldBySelector(measure.getTimestampField()).getAsPrimitive().getAsLong();
-    var point =
-        Point.measurement(measure.getMeasureName()).time((long) 
timestampValue, TimeUnit.MILLISECONDS);
+  private void iterateOverallEventProperties(
+      Event event,
+      Point.Builder point
+  ) {
 
-    for (var ep : measure.getEventSchema().getEventProperties()) {
+    allEventProperties.forEach(ep -> {
       var runtimeName = ep.getRuntimeName();
-      // timestamp should not be added as a field
-      if (!measure.getTimestampField().endsWith(runtimeName)) {
-        var sanitizedRuntimeName = sanitizedRuntimeNames.get(runtimeName);
-        var field = event.getOptionalFieldByRuntimeName(runtimeName);
-        try {
-          if (ep instanceof EventPropertyPrimitive) {
-            if (field.isPresent()) {
-              var eventPropertyPrimitiveField = field.get().getAsPrimitive();
-              if (eventPropertyPrimitiveField.getRawValue() == null) {
-                nullFields.add(sanitizedRuntimeName);
-              } else {
-
-                // store property as tag when the field is a dimension property
-                if 
(PropertyScope.DIMENSION_PROPERTY.name().equals(ep.getPropertyScope())) {
-                  point.tag(sanitizedRuntimeName, 
eventPropertyPrimitiveField.getAsString());
-                } else {
-                  handleMeasurementProperty(
-                      point,
-                      (EventPropertyPrimitive) ep,
-                      sanitizedRuntimeName,
-                      eventPropertyPrimitiveField);
-                }
-              }
-            } else {
-              missingFields.add(runtimeName);
-            }
-          } else {
-            // Since InfluxDB can't store non-primitive types, store them as 
string
-            // and deserialize later in downstream processes
-            if (field.isPresent()) {
-              handleNonPrimitiveMeasurementProperty(point, event, 
sanitizedRuntimeName);
-            } else {
-              missingFields.add(runtimeName);
-            }
-          }
-        } catch (SpRuntimeException iae) {
-          LOG.warn("Runtime exception while extracting field value of field {} 
- this field will be ignored",
-              runtimeName, iae);
+      var sanitizedRuntimeName = sanitizedRuntimeNames.get(runtimeName);
+      var fieldOptional = event.getOptionalFieldByRuntimeName(runtimeName);
+
+      fieldOptional.ifPresent(field -> {
+        if (ep instanceof EventPropertyPrimitive) {
+          propertyHandler.handlePrimitiveProperty(
+              point,
+              (EventPropertyPrimitive) ep,
+              field.getAsPrimitive(),
+              sanitizedRuntimeName
+          );
+        } else {
+          propertyHandler.handleNonPrimitiveProperty(
+              point,
+              event,
+              sanitizedRuntimeName
+          );
         }
-      }
-    }
+      });
+    });
+  }
 
-    if (missingFields.size() > 0) {
-      LOG.debug("Ignored {} fields which were present in the schema, but not 
in the provided event: {}",
-          missingFields.size(),
-          String.join(", ", missingFields));
-    }
 
-    if (nullFields.size() > 0) {
-      LOG.warn("Ignored {} fields which had a value 'null': {}", 
nullFields.size(), String.join(", ", nullFields));
-    }
-
-    influxDb.write(point.build());
+  /**
+   * Returns a list of the runtime names that are missing within the event
+   */
+  private List<String> getMissingProperties(
+      List<EventProperty> allEventProperties,
+      Event event
+  ) {
+    return allEventProperties.stream()
+                             .map(EventProperty::getRuntimeName)
+                             .filter(runtimeName -> 
event.getOptionalFieldByRuntimeName(runtimeName)
+                                                          .isEmpty())
+                             .collect(Collectors.toList());
   }
 
-  private void handleMeasurementProperty(Point.Builder p,
-                                         @NotNull EventPropertyPrimitive ep,
-                                         String preparedRuntimeName,
-                                         PrimitiveField 
eventPropertyPrimitiveField) {
-    try {
-      // Store property according to property type
-      var runtimeType = ep.getRuntimeType();
-      if (XSD.INTEGER.toString().equals(runtimeType)) {
-        try {
-          p.addField(preparedRuntimeName, 
eventPropertyPrimitiveField.getAsInt());
-        } catch (NumberFormatException ef) {
-          p.addField(preparedRuntimeName, 
eventPropertyPrimitiveField.getAsFloat());
-        }
-      } else if (XSD.LONG.toString().equals(runtimeType)) {
-        try {
-          p.addField(preparedRuntimeName, 
eventPropertyPrimitiveField.getAsLong());
-        } catch (NumberFormatException ef) {
-          p.addField(preparedRuntimeName, 
eventPropertyPrimitiveField.getAsFloat());
-        }
-      } else if (XSD.FLOAT.toString().equals(runtimeType)) {
-        p.addField(preparedRuntimeName, 
eventPropertyPrimitiveField.getAsFloat());
-      } else if (XSD.DOUBLE.toString().equals(runtimeType)) {
-        p.addField(preparedRuntimeName, 
eventPropertyPrimitiveField.getAsDouble());
-      } else if (XSD.BOOLEAN.toString().equals(runtimeType)) {
-        p.addField(preparedRuntimeName, 
eventPropertyPrimitiveField.getAsBoolean());
-      } else if (SO.NUMBER.equals(runtimeType)) {
-        p.addField(preparedRuntimeName, 
eventPropertyPrimitiveField.getAsDouble());
-      } else {
-        p.addField(preparedRuntimeName, 
eventPropertyPrimitiveField.getAsString());
-      }
-    } catch (NumberFormatException e) {
-      LOG.warn("Wrong number format for field {}, ignoring.", 
preparedRuntimeName);
+  private void checkEventIsNotNull(Event event) {
+    if (event == null) {
+      throw new SpRuntimeException("event is null");
     }
   }
 
-  private void handleNonPrimitiveMeasurementProperty(Point.Builder p, Event 
event, String preparedRuntimeName) {
-    try {
-      var json = 
rawFieldSerializer.serialize(event.getRaw().get(preparedRuntimeName));
-      p.addField(preparedRuntimeName, json);
-    } catch (SpRuntimeException e) {
-      LOG.warn("Failed to serialize field {}, ignoring.", preparedRuntimeName);
-    }
-  }
 
   /**
    * Shuts down the connection to the InfluxDB server
@@ -246,4 +188,55 @@ public class InfluxStore {
     }
     influxDb.close();
   }
+
+
+  /**
+   * Creates a point object which is later written to the influxDB and adds 
the value of the timestamp field
+   */
+  private Point.Builder initializePointWithTimestamp(Event event) {
+    var timestampValue = event.getFieldBySelector(measure.getTimestampField())
+                              .getAsPrimitive()
+                              .getAsLong();
+    return Point.measurement(measure.getMeasureName())
+                .time((long) timestampValue, TimeUnit.MILLISECONDS);
+  }
+
+  /**
+   * store sanitized target property runtime names in local variable
+   */
+  private void storeSanitizedRuntimeNames(DataLakeMeasure measure) {
+    measure.getEventSchema()
+           .getEventProperties()
+           .forEach(ep -> sanitizedRuntimeNames.put(
+               ep.getRuntimeName(),
+               InfluxNameSanitizer.renameReservedKeywords(ep.getRuntimeName())
+           ));
+  }
+
+  /**
+   * Returns all measurements properties except the timestamp field
+   */
+  private List<EventProperty> 
getAllEventPropertiesExceptTimestamp(DataLakeMeasure dataLakeMeasure) {
+    return dataLakeMeasure.getEventSchema()
+                          .getEventProperties()
+                          .stream()
+                          .filter(ep -> !dataLakeMeasure.getTimestampField()
+                                                        
.endsWith(ep.getRuntimeName()))
+                          .collect(Collectors.toList());
+  }
+
+  /**
+   * Iterates over all properties of the event and renames the key if it is a 
reserved keywords in InfluxDB
+   */
+  private void sanitizeRuntimeNamesInEvent(Event event) {
+    // sanitize event
+    for (var key : event.getRaw()
+                        .keySet()) {
+      if (InfluxDbReservedKeywords.KEYWORD_LIST.stream()
+                                               .anyMatch(k -> 
k.equalsIgnoreCase(key))) {
+        event.renameFieldByRuntimeName(key, key + "_");
+      }
+    }
+  }
+
 }
diff --git 
a/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/PropertyHandler.java
 
b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/PropertyHandler.java
new file mode 100644
index 000000000..9cc4a79d1
--- /dev/null
+++ 
b/streampipes-data-explorer-commons/src/main/java/org/apache/streampipes/dataexplorer/commons/influx/PropertyHandler.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.dataexplorer.commons.influx;
+
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import 
org.apache.streampipes.dataexplorer.commons.influx.serializer.RawFieldSerializer;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.model.runtime.field.PrimitiveField;
+import org.apache.streampipes.model.schema.EventPropertyPrimitive;
+import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.vocabulary.SO;
+import org.apache.streampipes.vocabulary.XSD;
+
+import org.influxdb.dto.Point;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PropertyHandler {
+
+  private static final Logger LOG = 
LoggerFactory.getLogger(PropertyHandler.class);
+
+  private RawFieldSerializer rawFieldSerializer;
+
+  public PropertyHandler() {
+    rawFieldSerializer = new RawFieldSerializer();
+  }
+
+  /**
+   * Takes properties of type primitive and stores them as tags or fields to 
the given point
+   */
+  public void handlePrimitiveProperty(
+      Point.Builder point,
+      EventPropertyPrimitive eventPropertyPrimitive,
+      PrimitiveField primitiveField,
+      String sanitizedRuntimeName
+  ) {
+    if (primitiveField.getRawValue() != null) {
+      // store property as tag when the field is a dimension property
+      if (PropertyScope.DIMENSION_PROPERTY.name()
+                                          
.equals(eventPropertyPrimitive.getPropertyScope())) {
+        handleDimensionProperty(
+            point,
+            primitiveField,
+            sanitizedRuntimeName
+        );
+      } else {
+        handleMeasurementProperty(
+            point,
+            eventPropertyPrimitive.getRuntimeType(),
+            sanitizedRuntimeName,
+            primitiveField
+        );
+      }
+    }
+  }
+
+
+  /**
+   * Takes non-primitive properties of and stores them as strings to the given 
point
+   * Since InfluxDB can't store non-primitive types, store them as string
+   * and deserialize later in downstream processes
+   */
+  public void handleNonPrimitiveProperty(
+      Point.Builder p,
+      Event event,
+      String preparedRuntimeName
+  ) {
+    try {
+      var json = rawFieldSerializer.serialize(event.getRaw()
+                                                   .get(preparedRuntimeName));
+      p.addField(preparedRuntimeName, json);
+    } catch (SpRuntimeException e) {
+      LOG.warn("Failed to serialize field {}, ignoring.", preparedRuntimeName);
+    }
+  }
+
+  /**
+   * Add dimension properties as tags to point
+   */
+  private void handleDimensionProperty(
+      Point.Builder point,
+      PrimitiveField primitiveField,
+      String sanitizedRuntimeName
+  ) {
+    point.tag(sanitizedRuntimeName, primitiveField.getAsString());
+  }
+
+  /**
+   * Transforms the given primitive property to the corresponding InfluxDB 
data type and adds it to the point
+   */
+  private void handleMeasurementProperty(
+      Point.Builder p,
+      String runtimeType,
+      String sanitizedRuntimeName,
+      PrimitiveField eventPropertyPrimitiveField
+  ) {
+    // Store property according to property type
+    if (XSD.INTEGER.toString()
+                   .equals(runtimeType)) {
+      handleIntegerProperty(p, sanitizedRuntimeName, 
eventPropertyPrimitiveField);
+    } else if (XSD.LONG.toString()
+                       .equals(runtimeType)) {
+      handleLongProperty(p, sanitizedRuntimeName, eventPropertyPrimitiveField);
+    } else if (XSD.FLOAT.toString()
+                        .equals(runtimeType)) {
+      handleFloatProperty(p, sanitizedRuntimeName, 
eventPropertyPrimitiveField);
+    } else if (XSD.DOUBLE.toString()
+                         .equals(runtimeType)) {
+      handleDoubleProperty(p, sanitizedRuntimeName, 
eventPropertyPrimitiveField);
+    } else if (XSD.BOOLEAN.toString()
+                          .equals(runtimeType)) {
+      handleBooleanProperty(p, sanitizedRuntimeName, 
eventPropertyPrimitiveField);
+    } else if (SO.NUMBER.equals(runtimeType)) {
+      handleDoubleProperty(p, sanitizedRuntimeName, 
eventPropertyPrimitiveField);
+    } else {
+      handleStringProperty(p, sanitizedRuntimeName, 
eventPropertyPrimitiveField);
+    }
+  }
+
+
+  private void handleStringProperty(
+      Point.Builder p,
+      String sanitizedRuntimeName,
+      PrimitiveField eventPropertyPrimitiveField
+  ) {
+    p.addField(sanitizedRuntimeName, 
eventPropertyPrimitiveField.getAsString());
+  }
+
+  private void handleBooleanProperty(
+      Point.Builder p,
+      String sanitizedRuntimeName,
+      PrimitiveField eventPropertyPrimitiveField
+  ) {
+    p.addField(sanitizedRuntimeName, 
eventPropertyPrimitiveField.getAsBoolean());
+  }
+
+  private void handleDoubleProperty(
+      Point.Builder p,
+      String sanitizedRuntimeName,
+      PrimitiveField eventPropertyPrimitiveField
+  ) {
+    p.addField(sanitizedRuntimeName, 
eventPropertyPrimitiveField.getAsDouble());
+  }
+
+  private void handleFloatProperty(
+      Point.Builder p,
+      String sanitizedRuntimeName,
+      PrimitiveField eventPropertyPrimitiveField
+  ) {
+    p.addField(sanitizedRuntimeName, eventPropertyPrimitiveField.getAsFloat());
+  }
+
+  private void handleLongProperty(
+      Point.Builder p,
+      String sanitizedRuntimeName,
+      PrimitiveField eventPropertyPrimitiveField
+  ) {
+    try {
+      p.addField(sanitizedRuntimeName, 
eventPropertyPrimitiveField.getAsLong());
+    } catch (NumberFormatException ef) {
+      handleFloatProperty(p, sanitizedRuntimeName, 
eventPropertyPrimitiveField);
+    }
+  }
+
+  private void handleIntegerProperty(
+      Point.Builder p,
+      String sanitizedRuntimeName,
+      PrimitiveField eventPropertyPrimitiveField
+  ) {
+    try {
+      p.addField(sanitizedRuntimeName, eventPropertyPrimitiveField.getAsInt());
+    } catch (NumberFormatException ef) {
+      handleFloatProperty(p, sanitizedRuntimeName, 
eventPropertyPrimitiveField);
+    }
+  }
+
+}
diff --git 
a/streampipes-data-explorer-commons/src/test/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxClientProviderTest.java
 
b/streampipes-data-explorer-commons/src/test/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxClientProviderTest.java
new file mode 100644
index 000000000..b0470669f
--- /dev/null
+++ 
b/streampipes-data-explorer-commons/src/test/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxClientProviderTest.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.dataexplorer.commons.influx;
+
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+
+import org.influxdb.InfluxDB;
+import org.influxdb.dto.Query;
+import org.influxdb.dto.QueryResult;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+
+public class InfluxClientProviderTest {
+
+  private InfluxDB influxDBMock;
+  private InfluxClientProvider influxClientProvider;
+
+  private static final String DATABASE_NAME = "testDB";
+
+  @Before
+  public void setUp() {
+    influxDBMock = mock(InfluxDB.class);
+    influxClientProvider = new InfluxClientProvider();
+  }
+
+  @Test
+  public void createDatabaseSuccess() {
+    var expectedQuery = new Query("CREATE DATABASE test", "");
+
+    influxClientProvider.createDatabase(influxDBMock, "test");
+
+    var pointArgumentCaptor = ArgumentCaptor.forClass(Query.class);
+    verify(influxDBMock).query(pointArgumentCaptor.capture());
+    var actualQuery = pointArgumentCaptor.getValue();
+
+    assertEquals(actualQuery.getDatabase(), expectedQuery.getDatabase());
+  }
+
+  @Test(expected = SpRuntimeException.class)
+  public void createDatabaseIlligalName() {
+    influxClientProvider.createDatabase(influxDBMock, "test%^$");
+  }
+
+  @Test
+  public void dataBaseDoesExist() {
+    var actualResult = testDataBaseExists(List.of(DATABASE_NAME));
+    assertTrue(actualResult);
+  }
+
+  @Test
+  public void dataBaseDoesNotExist() {
+    var actualResult = testDataBaseExists(List.of());
+    assertFalse(actualResult);
+  }
+
+  private boolean testDataBaseExists(List<Object> databaseNames) {
+    var queryResult = getQueryResultWithDatabaseNames(databaseNames);
+
+    when(influxDBMock.query(any())).thenReturn(queryResult);
+
+    return influxClientProvider.databaseExists(influxDBMock, DATABASE_NAME);
+  }
+
+  private QueryResult getQueryResultWithDatabaseNames(List<Object> 
databaseNames) {
+    var queryResult = mock(QueryResult.class);
+    var result = mock(QueryResult.Result.class);
+    when(queryResult.getResults()).thenReturn(List.of(result));
+    var series = mock(QueryResult.Series.class);
+    when(result.getSeries()).thenReturn(List.of(series));
+
+    List<List<Object>> values = List.of(databaseNames);
+    when(series.getValues()).thenReturn(values);
+    return queryResult;
+  }
+}
\ No newline at end of file
diff --git 
a/streampipes-data-explorer-commons/src/test/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxStoreTest.java
 
b/streampipes-data-explorer-commons/src/test/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxStoreTest.java
new file mode 100644
index 000000000..55ca38891
--- /dev/null
+++ 
b/streampipes-data-explorer-commons/src/test/java/org/apache/streampipes/dataexplorer/commons/influx/InfluxStoreTest.java
@@ -0,0 +1,395 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.dataexplorer.commons.influx;
+
+
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import 
org.apache.streampipes.dataexplorer.commons.influx.serializer.RawFieldSerializer;
+import org.apache.streampipes.model.datalake.DataLakeMeasure;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.model.runtime.EventFactory;
+import org.apache.streampipes.model.runtime.SchemaInfo;
+import org.apache.streampipes.model.runtime.SourceInfo;
+import org.apache.streampipes.model.schema.EventSchema;
+import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.test.generator.EventPropertyListTestBuilder;
+import org.apache.streampipes.test.generator.EventPropertyNestedTestBuilder;
+import org.apache.streampipes.test.generator.EventPropertyPrimitiveTestBuilder;
+import org.apache.streampipes.test.generator.EventSchemaTestBuilder;
+import org.apache.streampipes.vocabulary.SO;
+import org.apache.streampipes.vocabulary.XSD;
+
+import org.influxdb.InfluxDB;
+import org.influxdb.dto.Point;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class InfluxStoreTest {
+
+  private InfluxDB influxDBMock;
+
+  private RawFieldSerializer serializer;
+
+  private static final String EXPECTED_MEASUREMENT = "testMeasure";
+  private static final String FIELD_NAME = "testId";
+  private static final String TIMESTAMP = "timestamp";
+  private static final long SAMPLE_TIMESTAMP = 1701270890000L;
+
+  @Before
+  public void setUp() {
+    influxDBMock = mock(InfluxDB.class);
+    serializer = new RawFieldSerializer();
+  }
+
+  @Test
+  public void onEventNull() {
+    var influxStore = getInfluxStore(new EventSchema());
+    assertThrows(SpRuntimeException.class, () -> influxStore.onEvent(null));
+  }
+
+
+  @Test
+  public void onEventWithInteger() {
+    var expected = getPointBuilderWithTimestamp()
+        .addField(FIELD_NAME, 1)
+        .build();
+
+    var actualPoint = testEventWithOneField(XSD.INTEGER, 1);
+
+    assertEquals(expected, actualPoint);
+  }
+
+  @Test
+  public void onEventWithIntegerFloatValue() {
+    var expected = getPointBuilderWithTimestamp()
+        .addField(FIELD_NAME, 1.0f)
+        .build();
+
+    var actualPoint = testEventWithOneField(XSD.INTEGER, 1.0f);
+
+    assertEquals(expected, actualPoint);
+  }
+
+  @Test
+  public void onEventWithLong() {
+    var expected = getPointBuilderWithTimestamp()
+        .addField(FIELD_NAME, 1L)
+        .build();
+
+    var actualPoint = testEventWithOneField(XSD.LONG, 1L);
+
+    assertEquals(expected, actualPoint);
+  }
+
+  @Test
+  public void onEventWithLongFloatValue() {
+    var expected = getPointBuilderWithTimestamp()
+        .addField(FIELD_NAME, 1.0f)
+        .build();
+
+    var actualPoint = testEventWithOneField(XSD.LONG, 1.0f);
+
+    assertEquals(expected, actualPoint);
+  }
+
+  @Test
+  public void onEventWithFloat() {
+    var expected = getPointBuilderWithTimestamp()
+        .addField(FIELD_NAME, 1.0f)
+        .build();
+
+    var actualPoint = testEventWithOneField(XSD.FLOAT, 1.0f);
+
+    assertEquals(expected, actualPoint);
+  }
+
+  @Test
+  public void onEventWithDouble() {
+    var expected = getPointBuilderWithTimestamp()
+        .addField(FIELD_NAME, 1.0)
+        .build();
+
+    var actualPoint = testEventWithOneField(XSD.DOUBLE, 1.0);
+
+    assertEquals(expected, actualPoint);
+  }
+
+  @Test
+  public void onEventWithBoolean() {
+    var expected = getPointBuilderWithTimestamp()
+        .addField(FIELD_NAME, true)
+        .build();
+
+    var actualPoint = testEventWithOneField(XSD.BOOLEAN, true);
+
+    assertEquals(expected, actualPoint);
+  }
+
+  @Test
+  public void onEventWithNumber() throws URISyntaxException {
+    var expected = getPointBuilderWithTimestamp()
+        .addField(FIELD_NAME, 1.0)
+        .build();
+
+    var actualPoint = testEventWithOneField(new URI(SO.NUMBER), 1.0);
+
+    assertEquals(expected, actualPoint);
+  }
+
+  @Test
+  public void onEventWithString() {
+    var expected = getPointBuilderWithTimestamp()
+        .addField(FIELD_NAME, "testValue")
+        .build();
+
+    var actualPoint = testEventWithOneField(XSD.STRING, "testValue");
+
+    assertEquals(expected, actualPoint);
+  }
+
+  @Test
+  public void onEventReservedKeyWord() {
+    // name is a reserved keyword
+    var fieldName = "name";
+    var sanitizedFieldName = "name_";
+    var value = 1;
+
+    var expected = getPointBuilderWithTimestamp()
+        .addField(sanitizedFieldName, value)
+        .build();
+
+    var eventSchema = getEventSchemaBuilderWithTimestamp()
+        .withEventProperty(
+            EventPropertyPrimitiveTestBuilder
+                .create()
+                .withRuntimeName(sanitizedFieldName)
+                .withRuntimeType(XSD.INTEGER)
+                .build())
+        .build();
+
+    var event = getEvent(eventSchema, Map.of(fieldName, value));
+
+    var influxStore = getInfluxStore(eventSchema);
+
+    var actualPoint = executeOnEvent(influxStore, event);
+
+    assertEquals(expected, actualPoint);
+  }
+
+  @Test
+  public void onEventWithTag() {
+    var expected = getPointBuilderWithTimestamp()
+        .addField(FIELD_NAME, "value")
+        .tag("id", "id1")
+        .build();
+
+    var eventSchema = getEventSchemaBuilderWithTimestamp()
+        .withEventProperty(
+            EventPropertyPrimitiveTestBuilder
+                .create()
+                .withRuntimeName(FIELD_NAME)
+                .withRuntimeType(XSD.STRING)
+                .build())
+        .withEventProperty(
+            EventPropertyPrimitiveTestBuilder
+                .create()
+                .withRuntimeName("id")
+                .withRuntimeType(XSD.STRING)
+                .withPropertyScope(PropertyScope.DIMENSION_PROPERTY)
+                .build())
+        .build();
+
+    var event = getEvent(eventSchema, Map.of(FIELD_NAME, "value", "id", 
"id1"));
+
+    var influxStore = getInfluxStore(eventSchema);
+
+    var actualPoint = executeOnEvent(influxStore, event);
+
+    assertEquals(expected, actualPoint);
+  }
+
+
+  @Test
+  public void onEventWithNestedProperty() {
+    Map<String, Object> value = new HashMap<>();
+    value.put("one", "two");
+
+    var expected = getPointBuilderWithTimestamp()
+        .addField(FIELD_NAME, serializer.serialize(value))
+        .build();
+
+    var eventSchema = getEventSchemaBuilderWithTimestamp()
+        .withEventProperty(
+            EventPropertyNestedTestBuilder
+                .create()
+                .withRuntimeName(FIELD_NAME)
+                .build())
+        .build();
+
+    var event = getEvent(eventSchema, Map.of(FIELD_NAME, value));
+
+    var influxStore = getInfluxStore(eventSchema);
+
+    var actualPoint = executeOnEvent(influxStore, event);
+
+    assertEquals(expected, actualPoint);
+  }
+
+  @Test
+  public void onEventWithListProperty() {
+    String[] value = {"one", "two"};
+    var expected = getPointBuilderWithTimestamp()
+        .addField(FIELD_NAME, serializer.serialize(value))
+        .build();
+
+    var eventSchema = getEventSchemaBuilderWithTimestamp()
+        .withEventProperty(
+            EventPropertyListTestBuilder
+                .create()
+                .withRuntimeName(FIELD_NAME)
+                .build())
+        .build();
+
+    var event = getEvent(eventSchema, Map.of(FIELD_NAME, value));
+
+    var influxStore = getInfluxStore(eventSchema);
+
+    var actualPoint = executeOnEvent(influxStore, event);
+
+    assertEquals(expected, actualPoint);
+  }
+
+  /**
+   * Initialize a Point builder with a timestamp
+   */
+  private Point.Builder getPointBuilderWithTimestamp() {
+    return Point.measurement(EXPECTED_MEASUREMENT)
+                .time(SAMPLE_TIMESTAMP, TimeUnit.MILLISECONDS);
+  }
+
+
+  /**
+   * Executes the onEvent method and returns the resuting data point using an 
argument captor
+   */
+  private Point executeOnEvent(InfluxStore influxStore, Event event) {
+    influxStore.onEvent(event);
+    var pointArgumentCaptor = ArgumentCaptor.forClass(Point.class);
+
+    verify(influxDBMock).write(pointArgumentCaptor.capture());
+
+    var actualPoint = pointArgumentCaptor.getValue();
+    return actualPoint;
+  }
+
+  /**
+   * Creates an event with the given data and a timestamp
+   */
+  private Event getEvent(EventSchema eventSchema, Map<String, Object> 
inputData) {
+    Map<String, Object> data = new HashMap<>();
+    data.put(TIMESTAMP, SAMPLE_TIMESTAMP);
+    data.putAll(inputData);
+
+    return EventFactory.fromMap(
+        data,
+        new SourceInfo("test-topic", "s0"),
+        new SchemaInfo(eventSchema, new ArrayList<>())
+    );
+  }
+
+
+  /**
+   * This convenience method is used to test all cases for the different 
supported data types
+   */
+  private Point testEventWithOneField(
+      URI type,
+      Object value
+  ) {
+
+    var eventSchema = getEventSchemaBuilderWithTimestamp()
+        .withEventProperty(
+            EventPropertyPrimitiveTestBuilder
+                .create()
+                .withRuntimeName(FIELD_NAME)
+                .withRuntimeType(type)
+                .build())
+        .build();
+
+
+    var event = EventFactory.fromMap(
+        Map.of(TIMESTAMP, SAMPLE_TIMESTAMP, FIELD_NAME, value),
+        new SourceInfo("test-topic", "s0"),
+        new SchemaInfo(eventSchema, new ArrayList<>())
+    );
+
+    var influxStore = getInfluxStore(eventSchema);
+
+    influxStore.onEvent(event);
+    var pointArgumentCaptor = ArgumentCaptor.forClass(Point.class);
+
+    verify(influxDBMock).write(pointArgumentCaptor.capture());
+    return pointArgumentCaptor.getValue();
+  }
+
+  /**
+   * Returns the event schema builder with a default timestamp property
+   */
+  private EventSchemaTestBuilder getEventSchemaBuilderWithTimestamp() {
+    return EventSchemaTestBuilder
+        .create()
+        .withEventProperty(
+            EventPropertyPrimitiveTestBuilder
+                .create()
+                .withRuntimeName(TIMESTAMP)
+                .build());
+  }
+
+  /**
+   * Initializes an influx store with the given event schema
+   */
+  private InfluxStore getInfluxStore(EventSchema eventSchema) {
+
+    DataLakeMeasure measure = new DataLakeMeasure(
+        EXPECTED_MEASUREMENT,
+        "s0::%s".formatted(TIMESTAMP),
+        eventSchema
+    );
+
+    var influxClientProviderMock = mock(InfluxClientProvider.class);
+    when(influxClientProviderMock.getInitializedInfluxDBClient(any()))
+        .thenReturn(influxDBMock);
+
+    return new InfluxStore(measure, null, influxClientProviderMock);
+  }
+
+}
\ No newline at end of file
diff --git 
a/streampipes-extensions/streampipes-connectors-influx/src/main/java/org/apache/streampipes/extensions/connectors/influx/adapter/InfluxDbClient.java
 
b/streampipes-extensions/streampipes-connectors-influx/src/main/java/org/apache/streampipes/extensions/connectors/influx/adapter/InfluxDbClient.java
index 81a9da6cc..b370f415f 100644
--- 
a/streampipes-extensions/streampipes-connectors-influx/src/main/java/org/apache/streampipes/extensions/connectors/influx/adapter/InfluxDbClient.java
+++ 
b/streampipes-extensions/streampipes-connectors-influx/src/main/java/org/apache/streampipes/extensions/connectors/influx/adapter/InfluxDbClient.java
@@ -20,8 +20,8 @@ package 
org.apache.streampipes.extensions.connectors.influx.adapter;
 
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.commons.exceptions.connect.AdapterException;
+import org.apache.streampipes.dataexplorer.commons.influx.InfluxClientProvider;
 import 
org.apache.streampipes.dataexplorer.commons.influx.InfluxConnectionSettings;
-import org.apache.streampipes.dataexplorer.commons.influx.InfluxRequests;
 import 
org.apache.streampipes.extensions.connectors.influx.shared.SharedInfluxClient;
 import org.apache.streampipes.model.connect.guess.GuessSchema;
 import org.apache.streampipes.model.schema.EventProperty;
@@ -56,6 +56,8 @@ public class InfluxDbClient extends SharedInfluxClient {
 
   private boolean connected;
 
+  private final InfluxClientProvider influxClientProvider;
+
   public static class Column {
     private final String name;
     private final Datatypes datatypes;
@@ -79,6 +81,7 @@ public class InfluxDbClient extends SharedInfluxClient {
                  boolean replaceNullValues) {
     super(connectionSettings, measurement);
     this.replaceNullValues = replaceNullValues;
+    this.influxClientProvider = new InfluxClientProvider();
 
     this.connected = false;
   }
@@ -89,7 +92,7 @@ public class InfluxDbClient extends SharedInfluxClient {
       var database = connectionSettings.getDatabaseName();
 
       // Checking whether the database exists
-      if (!InfluxRequests.databaseExists(influxDb, database)) {
+      if (!influxClientProvider.databaseExists(influxDb, database)) {
         throw new AdapterException("Database " + database + " could not be 
found.");
       }
 
diff --git 
a/streampipes-extensions/streampipes-connectors-influx/src/main/java/org/apache/streampipes/extensions/connectors/influx/sink/InfluxDbClient.java
 
b/streampipes-extensions/streampipes-connectors-influx/src/main/java/org/apache/streampipes/extensions/connectors/influx/sink/InfluxDbClient.java
index d81938839..63b8ce2f6 100644
--- 
a/streampipes-extensions/streampipes-connectors-influx/src/main/java/org/apache/streampipes/extensions/connectors/influx/sink/InfluxDbClient.java
+++ 
b/streampipes-extensions/streampipes-connectors-influx/src/main/java/org/apache/streampipes/extensions/connectors/influx/sink/InfluxDbClient.java
@@ -19,8 +19,8 @@
 package org.apache.streampipes.extensions.connectors.influx.sink;
 
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.dataexplorer.commons.influx.InfluxClientProvider;
 import 
org.apache.streampipes.dataexplorer.commons.influx.InfluxConnectionSettings;
-import org.apache.streampipes.dataexplorer.commons.influx.InfluxRequests;
 import 
org.apache.streampipes.extensions.connectors.influx.shared.SharedInfluxClient;
 import org.apache.streampipes.model.runtime.Event;
 
@@ -41,6 +41,8 @@ public class InfluxDbClient extends SharedInfluxClient {
   private final Integer batchSize;
   private final Integer flushDuration;
 
+  private final InfluxClientProvider influxClientProvider;
+
 
   InfluxDbClient(InfluxConnectionSettings connectionSettings,
                  String measureName,
@@ -52,6 +54,7 @@ public class InfluxDbClient extends SharedInfluxClient {
     this.timestampField = timestampField;
     this.batchSize = batchSize;
     this.flushDuration = flushDuration;
+    this.influxClientProvider = new InfluxClientProvider();
 
     connect();
   }
@@ -67,7 +70,7 @@ public class InfluxDbClient extends SharedInfluxClient {
     var databaseName = connectionSettings.getDatabaseName();
 
     // Checking whether the database exists
-    if (!InfluxRequests.databaseExists(influxDb, databaseName)) {
+    if (!influxClientProvider.databaseExists(influxDb, databaseName)) {
       LOG.info("Database '" + databaseName + "' not found. Gets created ...");
       createDatabase(databaseName);
     }
diff --git 
a/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java
 
b/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyListTestBuilder.java
similarity index 55%
copy from 
streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java
copy to 
streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyListTestBuilder.java
index 8fd69330d..2ac224a05 100644
--- 
a/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java
+++ 
b/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyListTestBuilder.java
@@ -15,35 +15,30 @@
  * limitations under the License.
  *
  */
-package org.apache.streampipes.test.generator;
 
-import org.apache.streampipes.model.schema.EventPropertyPrimitive;
+package org.apache.streampipes.test.generator;
 
-import java.net.URI;
-import java.util.List;
+import org.apache.streampipes.model.schema.EventPropertyList;
 
-public class EventPropertyPrimitiveTestBuilder
-    extends EventPropertyTestBuilder<EventPropertyPrimitive, 
EventPropertyPrimitiveTestBuilder> {
+public class EventPropertyListTestBuilder
+    extends EventPropertyTestBuilder<EventPropertyList, 
EventPropertyListTestBuilder> {
 
-  protected EventPropertyPrimitiveTestBuilder() {
-    super(new EventPropertyPrimitive());
+  protected EventPropertyListTestBuilder() {
+    super(new EventPropertyList());
   }
 
-  public EventPropertyPrimitiveTestBuilder withSemanticType(String 
semanticType) {
-    this.eventProperty.setDomainProperties(List.of(URI.create(semanticType)));
-    return this;
+  public static EventPropertyNestedTestBuilder create() {
+    return new EventPropertyNestedTestBuilder();
   }
 
-  public static EventPropertyPrimitiveTestBuilder create() {
-    return new EventPropertyPrimitiveTestBuilder();
+  @Override
+  protected EventPropertyListTestBuilder me() {
+    return this;
   }
 
   @Override
-  public EventPropertyPrimitive build() {
+  public EventPropertyList build() {
     return eventProperty;
   }
 
-  protected EventPropertyPrimitiveTestBuilder me() {
-    return this;
-  }
-}
+}
\ No newline at end of file
diff --git 
a/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java
 
b/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java
index 8fd69330d..fc5c1babc 100644
--- 
a/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java
+++ 
b/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java
@@ -18,6 +18,7 @@
 package org.apache.streampipes.test.generator;
 
 import org.apache.streampipes.model.schema.EventPropertyPrimitive;
+import org.apache.streampipes.model.schema.PropertyScope;
 
 import java.net.URI;
 import java.util.List;
@@ -29,6 +30,16 @@ public class EventPropertyPrimitiveTestBuilder
     super(new EventPropertyPrimitive());
   }
 
+  public EventPropertyPrimitiveTestBuilder withRuntimeType(URI runtimeType) {
+    this.eventProperty.setRuntimeType(runtimeType.toString());
+    return this;
+  }
+
+  public EventPropertyPrimitiveTestBuilder withPropertyScope(PropertyScope 
propertyScope) {
+    this.eventProperty.setPropertyScope(propertyScope.toString());
+    return this;
+  }
+
   public EventPropertyPrimitiveTestBuilder withSemanticType(String 
semanticType) {
     this.eventProperty.setDomainProperties(List.of(URI.create(semanticType)));
     return this;

Reply via email to