diff --git a/theodolite-benchmarks/http-bridge/build.gradle b/theodolite-benchmarks/http-bridge/build.gradle index 1f1e40f3e3546eba2a91aecc121c43b4ed28cf31..0377eefc76b456d8e0f94087b06d0c2689f977cf 100644 --- a/theodolite-benchmarks/http-bridge/build.gradle +++ b/theodolite-benchmarks/http-bridge/build.gradle @@ -24,7 +24,8 @@ dependencies { implementation project(':load-generator-commons') implementation 'io.javalin:javalin:4.3.0' - implementation 'org.slf4j:slf4j-simple:1.7.25' + implementation 'com.google.code.gson:gson:2.8.2' + runtimeOnly 'org.slf4j:slf4j-simple:1.7.25' testImplementation 'junit:junit:4.12' } diff --git a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/Deserializer.java b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/Deserializer.java index 248dd0fbbb9b42ebea6230c77203db7f93bc63ff..f25c120d2165c4a1f747fdba32de43d4e4d157a6 100644 --- a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/Deserializer.java +++ b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/Deserializer.java @@ -1,5 +1,10 @@ package theodolite.commons.httpbridge; +/** + * A class for converting objects to strings. + * + * @param <T> Type to be deserialized from. + */ @FunctionalInterface public interface Deserializer<T> { diff --git a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/Endpoint.java b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/Endpoint.java index d403d08fad63972e395c993525bc71828139a6fe..43850d80699a0db0b0fcebd76f625a17f8133f30 100644 --- a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/Endpoint.java +++ b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/Endpoint.java @@ -2,6 +2,12 @@ package theodolite.commons.httpbridge; import theodolite.commons.workloadgeneration.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; @@ -10,6 +16,9 @@ public class Endpoint<T> { 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, @@ -19,6 +28,9 @@ public class Endpoint<T> { 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, diff --git a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/EnvVarHttpBridgeFactory.java b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/EnvVarHttpBridgeFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..97956b8d47185c90efdc03393c03c8c44aea2335 --- /dev/null +++ b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/EnvVarHttpBridgeFactory.java @@ -0,0 +1,59 @@ +package theodolite.commons.httpbridge; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import theodolite.commons.workloadgeneration.ConfigurationKeys; +import theodolite.commons.workloadgeneration.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/theodolite/commons/httpbridge/GsonDeserializer.java b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/GsonDeserializer.java index 0502a0606d3e2206ecfad3628cb6463dc1f1c02a..42220617546527157d5463d6b9ce9208abc66d58 100644 --- a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/GsonDeserializer.java +++ b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/GsonDeserializer.java @@ -2,6 +2,11 @@ package theodolite.commons.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; diff --git a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/HttpBridge.java b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/HttpBridge.java index b9f1c3c27aaae09f48b9f2ca03b3222b29b252e7..d36e191c8b0a591107de796f511aa853063dff73 100644 --- a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/HttpBridge.java +++ b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/HttpBridge.java @@ -1,22 +1,40 @@ package theodolite.commons.httpbridge; import java.util.List; -import theodolite.commons.workloadgeneration.TitanKafkaSenderFactory; -import titan.ccp.model.records.ActivePowerRecord; +import theodolite.commons.workloadgeneration.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 static final int PORT = 8080; - private static final String HOST = "0.0.0.0"; // NOPMD + private final JavalinWebServer webServer; - public void run() { - final Endpoint<?> converter = new Endpoint<>( - "/", - ActivePowerRecord.class, - TitanKafkaSenderFactory.forKafkaConfig(null, null, null)); + 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(); + } - final JavalinWebServer webServer = new JavalinWebServer(List.of(converter), HOST, PORT); - webServer.start(); + public static void main(final String[] args) { + HttpBridge.fromEnvironment().runAsStandalone(); } } diff --git a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/JavalinWebServer.java b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/JavalinWebServer.java index 1513156b4181287394e4d7be2fd48ef807153dbe..4e35172913211d16818228f5df73e1232164a066 100644 --- a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/JavalinWebServer.java +++ b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/JavalinWebServer.java @@ -3,6 +3,9 @@ package theodolite.commons.httpbridge; import io.javalin.Javalin; import java.util.Collection; +/** + * Implementation of a webserver based on the Javalin framework. + */ public class JavalinWebServer { private static final int HTTP_SUCCESS = 200; @@ -12,6 +15,9 @@ public class JavalinWebServer { 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,