diff --git a/broker/pom.xml b/broker/pom.xml
index 0983c4c8599b..dcba060cbbd7 100644
--- a/broker/pom.xml
+++ b/broker/pom.xml
@@ -31,11 +31,6 @@
jackson-datatype-jsr310
-
- com.google.code.gson
- gson
-
-
com.google.guava
guava
diff --git a/broker/src/main/java/io/camunda/zeebe/broker/exporter/context/ExporterConfiguration.java b/broker/src/main/java/io/camunda/zeebe/broker/exporter/context/ExporterConfiguration.java
index 4b13c6b9088d..64e3e10214d6 100644
--- a/broker/src/main/java/io/camunda/zeebe/broker/exporter/context/ExporterConfiguration.java
+++ b/broker/src/main/java/io/camunda/zeebe/broker/exporter/context/ExporterConfiguration.java
@@ -7,25 +7,27 @@
*/
package io.camunda.zeebe.broker.exporter.context;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonElement;
-import io.camunda.zeebe.exporter.api.ExporterException;
+import com.fasterxml.jackson.core.JsonParser.Feature;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
import io.camunda.zeebe.exporter.api.context.Configuration;
+import io.camunda.zeebe.util.ReflectUtil;
import java.util.Map;
-public final class ExporterConfiguration implements Configuration {
- private static final Gson CONFIG_INSTANTIATOR = new GsonBuilder().create();
+public record ExporterConfiguration(String id, Map arguments)
+ implements Configuration {
- private final String id;
- private final Map arguments;
-
- private JsonElement intermediateConfiguration;
-
- public ExporterConfiguration(final String id, final Map arguments) {
- this.id = id;
- this.arguments = arguments;
- }
+ // Accepts more lenient cases, such that the property "something" would match a field "someThing"
+ // Note however that if a field "something" and "someThing" are present, only one of them will be
+ // instantiated (the last declared one), using the last matching value.
+ private static final ObjectMapper MAPPER =
+ JsonMapper.builder()
+ .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
+ .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
+ .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_VALUES)
+ .enable(Feature.IGNORE_UNDEFINED, Feature.ALLOW_SINGLE_QUOTES)
+ .build();
@Override
public String getId() {
@@ -40,25 +42,9 @@ public Map getArguments() {
@Override
public T instantiate(final Class configClass) {
if (arguments != null) {
- return CONFIG_INSTANTIATOR.fromJson(getIntermediateConfiguration(), configClass);
+ return MAPPER.convertValue(arguments, configClass);
} else {
- try {
- return configClass.newInstance();
- } catch (final Exception e) {
- throw new ExporterException(
- "Unable to instantiate config class "
- + configClass.getName()
- + " with default constructor",
- e);
- }
+ return ReflectUtil.newInstance(configClass);
}
}
-
- private JsonElement getIntermediateConfiguration() {
- if (intermediateConfiguration == null) {
- intermediateConfiguration = CONFIG_INSTANTIATOR.toJsonTree(arguments);
- }
-
- return intermediateConfiguration;
- }
}
diff --git a/broker/src/main/java/io/camunda/zeebe/broker/exporter/repo/ExporterDescriptor.java b/broker/src/main/java/io/camunda/zeebe/broker/exporter/repo/ExporterDescriptor.java
index 16d5dfa6f2ae..4577d52f5817 100644
--- a/broker/src/main/java/io/camunda/zeebe/broker/exporter/repo/ExporterDescriptor.java
+++ b/broker/src/main/java/io/camunda/zeebe/broker/exporter/repo/ExporterDescriptor.java
@@ -37,6 +37,6 @@ public ExporterConfiguration getConfiguration() {
}
public String getId() {
- return configuration.getId();
+ return configuration.id();
}
}
diff --git a/broker/src/test/java/io/camunda/zeebe/broker/exporter/context/ExporterConfigurationTest.java b/broker/src/test/java/io/camunda/zeebe/broker/exporter/context/ExporterConfigurationTest.java
new file mode 100644
index 000000000000..3ebd6b0564c0
--- /dev/null
+++ b/broker/src/test/java/io/camunda/zeebe/broker/exporter/context/ExporterConfigurationTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
+ * one or more contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright ownership.
+ * Licensed under the Zeebe Community License 1.1. You may not use this file
+ * except in compliance with the Zeebe Community License 1.1.
+ */
+package io.camunda.zeebe.broker.exporter.context;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Map;
+import org.junit.jupiter.api.parallel.Execution;
+import org.junit.jupiter.api.parallel.ExecutionMode;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+@Execution(ExecutionMode.CONCURRENT)
+final class ExporterConfigurationTest {
+ @ParameterizedTest
+ @ValueSource(strings = {"numberofshards", "numberOfShards", "NUMBEROFSHARDS"})
+ void shouldInstantiateConfigWithCaseInsensitiveProperties(final String property) {
+ // given
+ final var args = Map.of(property, 1);
+ final var expected = new Config(1);
+ final var config = new ExporterConfiguration("id", args);
+
+ // when
+ final var instance = config.instantiate(Config.class);
+
+ // then
+ assertThat(instance).isEqualTo(expected);
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"numberofshards", "numberOfShards", "NUMBEROFSHARDS"})
+ void shouldInstantiateNestedConfigWithCaseInsensitiveProperties(final String property) {
+ // given
+ final var args = Map.of("nested", Map.of(property, 1));
+ final var expected = new ContainerConfig(new Config(1));
+ final var config = new ExporterConfiguration("id", args);
+
+ // when
+ final var instance = config.instantiate(ContainerConfig.class);
+
+ // then
+ assertThat(instance).isEqualTo(expected);
+ }
+
+ private record Config(int numberOfShards) {}
+
+ private record ContainerConfig(Config nested) {}
+}
diff --git a/broker/src/test/java/io/camunda/zeebe/broker/exporter/repo/ExporterRepositoryTest.java b/broker/src/test/java/io/camunda/zeebe/broker/exporter/repo/ExporterRepositoryTest.java
index 61ccdc1c26de..1c45f97a6aae 100644
--- a/broker/src/test/java/io/camunda/zeebe/broker/exporter/repo/ExporterRepositoryTest.java
+++ b/broker/src/test/java/io/camunda/zeebe/broker/exporter/repo/ExporterRepositoryTest.java
@@ -94,8 +94,8 @@ void shouldLoadExternalExporter(final @TempDir File tempDir) throws Exception {
// then
assertThat(config.isExternal()).isTrue();
- assertThat(descriptor.getConfiguration().getArguments()).isEqualTo(config.getArgs());
- assertThat(descriptor.getConfiguration().getId()).isEqualTo("exported");
+ assertThat(descriptor.getConfiguration().arguments()).isEqualTo(config.getArgs());
+ assertThat(descriptor.getConfiguration().id()).isEqualTo("exported");
assertThat(descriptor.newInstance().getClass().getCanonicalName())
.isEqualTo(ExternalExporter.EXPORTER_CLASS_NAME);
}
diff --git a/parent/pom.xml b/parent/pom.xml
index 9c7c5dbcfa4f..c876793ecc9f 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -606,12 +606,6 @@
${version.guava}
-
- com.google.code.gson
- gson
- ${version.gson}
-
-
io.zeebe
zeebe-test-container
@@ -924,6 +918,13 @@
hamcrest-core
${version.hamcrest}
+
+
+
+ com.google.code.gson
+ gson
+ ${version.gson}
+
diff --git a/qa/integration-tests/pom.xml b/qa/integration-tests/pom.xml
index 0910b6e96eee..b1a915af9464 100644
--- a/qa/integration-tests/pom.xml
+++ b/qa/integration-tests/pom.xml
@@ -251,12 +251,6 @@
test
-
- org.springframework.boot
- spring-boot
- test
-
-
org.mockito
mockito-core
diff --git a/qa/integration-tests/src/test/java/io/camunda/zeebe/it/smoke/StandaloneBrokerIT.java b/qa/integration-tests/src/test/java/io/camunda/zeebe/it/smoke/StandaloneBrokerIT.java
index 3fdf5b8afe18..70da58db7be7 100644
--- a/qa/integration-tests/src/test/java/io/camunda/zeebe/it/smoke/StandaloneBrokerIT.java
+++ b/qa/integration-tests/src/test/java/io/camunda/zeebe/it/smoke/StandaloneBrokerIT.java
@@ -27,7 +27,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
-import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;