diff --git a/spring-boot-starter-camunda/src/main/java/io/camunda/zeebe/spring/client/configuration/ZeebeClientAllAutoConfiguration.java b/spring-boot-starter-camunda/src/main/java/io/camunda/zeebe/spring/client/configuration/ZeebeClientAllAutoConfiguration.java index 2b3a3a2f6..f43357bb5 100644 --- a/spring-boot-starter-camunda/src/main/java/io/camunda/zeebe/spring/client/configuration/ZeebeClientAllAutoConfiguration.java +++ b/spring-boot-starter-camunda/src/main/java/io/camunda/zeebe/spring/client/configuration/ZeebeClientAllAutoConfiguration.java @@ -2,6 +2,7 @@ import io.camunda.zeebe.client.api.JsonMapper; import io.camunda.zeebe.client.api.worker.BackoffSupplier; +import io.camunda.zeebe.client.impl.ZeebeClientImpl; import io.camunda.zeebe.client.impl.worker.ExponentialBackoffBuilderImpl; import io.camunda.zeebe.spring.client.annotation.customizer.ZeebeWorkerValueCustomizer; import io.camunda.zeebe.spring.client.annotation.processor.AnnotationProcessorConfiguration; @@ -12,18 +13,20 @@ import io.camunda.zeebe.spring.client.metrics.MetricsRecorder; import io.camunda.zeebe.spring.client.properties.PropertyBasedZeebeWorkerValueCustomizer; import io.camunda.zeebe.spring.client.properties.ZeebeClientConfigurationProperties; +import io.grpc.ManagedChannel; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; -@ConditionalOnProperty(prefix = "zeebe.client", name = "enabled", havingValue = "true", matchIfMissing = true) +@ConditionalOnProperty(prefix = "zeebe.client", name = "enabled", havingValue = "true", matchIfMissing = true) @Import(AnnotationProcessorConfiguration.class) @EnableConfigurationProperties(ZeebeClientConfigurationProperties.class) public class ZeebeClientAllAutoConfiguration { private final ZeebeClientConfigurationProperties configurationProperties; + public ZeebeClientAllAutoConfiguration(ZeebeClientConfigurationProperties configurationProperties) { this.configurationProperties = configurationProperties; } @@ -40,6 +43,12 @@ public CommandExceptionHandlingStrategy commandExceptionHandlingStrategy(ZeebeCl return new DefaultCommandExceptionHandlingStrategy(backoffSupplier(), scheduledExecutorService.get()); } + @Bean + @ConditionalOnMissingBean(ZeebeClientManagedChannelFactory.class) + public ZeebeClientManagedChannelFactory defaultManagedChannelFactory() { + return new DefaultZeebeClientManagedChannelFactory(); + } + @Bean public JobWorkerManager jobWorkerManager(final CommandExceptionHandlingStrategy commandExceptionHandlingStrategy, final JsonMapper jsonMapper, @@ -63,5 +72,10 @@ public ZeebeWorkerValueCustomizer propertyBasedZeebeWorkerValueCustomizer() { return new PropertyBasedZeebeWorkerValueCustomizer(this.configurationProperties); } - + public static final class DefaultZeebeClientManagedChannelFactory implements ZeebeClientManagedChannelFactory { + @Override + public ManagedChannel createChannel(ZeebeClientConfigurationProperties configurationProperties) { + return ZeebeClientImpl.buildChannel(configurationProperties); + } + } } diff --git a/spring-boot-starter-camunda/src/main/java/io/camunda/zeebe/spring/client/configuration/ZeebeClientManagedChannelFactory.java b/spring-boot-starter-camunda/src/main/java/io/camunda/zeebe/spring/client/configuration/ZeebeClientManagedChannelFactory.java new file mode 100644 index 000000000..a7fc079c3 --- /dev/null +++ b/spring-boot-starter-camunda/src/main/java/io/camunda/zeebe/spring/client/configuration/ZeebeClientManagedChannelFactory.java @@ -0,0 +1,8 @@ +package io.camunda.zeebe.spring.client.configuration; + +import io.camunda.zeebe.spring.client.properties.ZeebeClientConfigurationProperties; +import io.grpc.ManagedChannel; + +public interface ZeebeClientManagedChannelFactory { + ManagedChannel createChannel(ZeebeClientConfigurationProperties configurationProperties); +} diff --git a/spring-boot-starter-camunda/src/main/java/io/camunda/zeebe/spring/client/configuration/ZeebeClientProdAutoConfiguration.java b/spring-boot-starter-camunda/src/main/java/io/camunda/zeebe/spring/client/configuration/ZeebeClientProdAutoConfiguration.java index 9ff2577e7..52c725839 100644 --- a/spring-boot-starter-camunda/src/main/java/io/camunda/zeebe/spring/client/configuration/ZeebeClientProdAutoConfiguration.java +++ b/spring-boot-starter-camunda/src/main/java/io/camunda/zeebe/spring/client/configuration/ZeebeClientProdAutoConfiguration.java @@ -32,10 +32,12 @@ public class ZeebeClientProdAutoConfiguration { private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private final ZeebeClientConfigurationProperties configurationProperties; + private final ZeebeClientManagedChannelFactory zeebeClientManagedChannelFactory; private final ZeebeClientExecutorService zeebeClientExecutorService; - public ZeebeClientProdAutoConfiguration(ZeebeClientConfigurationProperties configurationProperties, ZeebeClientExecutorService zeebeClientExecutorService, JsonMapper jsonMapper) { + public ZeebeClientProdAutoConfiguration(ZeebeClientConfigurationProperties configurationProperties, ZeebeClientExecutorService zeebeClientExecutorService, JsonMapper jsonMapper, ZeebeClientManagedChannelFactory zeebeClientManagedChannelFactory) { this.configurationProperties = configurationProperties; + this.zeebeClientManagedChannelFactory = zeebeClientManagedChannelFactory; configurationProperties.setJsonMapper(jsonMapper); // Replace JsonMapper proxy (because of lazy) with real bean configurationProperties.applyOverrides(); // make sure environment variables and other legacy config options are taken into account (duplicate, also done by qPostConstruct, whatever) @@ -49,11 +51,11 @@ public ZeebeClient zeebeClient() { // (ZeebeClientBuilder builder) { LOG.info("Creating ZeebeClient using ZeebeClientConfiguration [" + configurationProperties + "]"); if (zeebeClientExecutorService!=null) { - ManagedChannel managedChannel = ZeebeClientImpl.buildChannel(configurationProperties); + ManagedChannel managedChannel = this.zeebeClientManagedChannelFactory.createChannel(configurationProperties); GatewayGrpc.GatewayStub gatewayStub = ZeebeClientImpl.buildGatewayStub(managedChannel, configurationProperties); return new ZeebeClientImpl(configurationProperties, managedChannel, gatewayStub, zeebeClientExecutorService.get()); } else { - return new ZeebeClientImpl(configurationProperties); + return new ZeebeClientImpl(configurationProperties, zeebeClientManagedChannelFactory.createChannel(configurationProperties)); } } // TODO: Interceptors diff --git a/spring-boot-starter-camunda/src/test/java/io/camunda/zeebe/spring/client/config/ZeebeClientStarterAutoConfigurationCustomZeebeClientManagedChannelFactoryTest.java b/spring-boot-starter-camunda/src/test/java/io/camunda/zeebe/spring/client/config/ZeebeClientStarterAutoConfigurationCustomZeebeClientManagedChannelFactoryTest.java new file mode 100644 index 000000000..fdc914b36 --- /dev/null +++ b/spring-boot-starter-camunda/src/test/java/io/camunda/zeebe/spring/client/config/ZeebeClientStarterAutoConfigurationCustomZeebeClientManagedChannelFactoryTest.java @@ -0,0 +1,98 @@ +package io.camunda.zeebe.spring.client.config; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.camunda.zeebe.client.ZeebeClient; +import io.camunda.zeebe.client.api.JsonMapper; +import io.camunda.zeebe.client.impl.ZeebeClientImpl; +import io.camunda.zeebe.spring.client.CamundaAutoConfiguration; +import io.camunda.zeebe.spring.client.configuration.ZeebeClientManagedChannelFactory; +import io.camunda.zeebe.spring.client.configuration.ZeebeClientProdAutoConfiguration; +import io.camunda.zeebe.spring.client.properties.ZeebeClientConfigurationProperties; +import io.grpc.ManagedChannel; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(SpringExtension.class) +@TestPropertySource( + properties = { + "zeebe.client.broker.gatewayAddress=localhost12345", + "zeebe.client.requestTimeout=99s", + "zeebe.client.job.timeout=99s", + "zeebe.client.job.pollInterval=99s", + "zeebe.client.worker.maxJobsActive=99", + "zeebe.client.worker.threads=99", + "zeebe.client.worker.defaultName=testName", + "zeebe.client.worker.defaultType=testType", + "zeebe.client.worker.override.foo.enabled=false", + "zeebe.client.message.timeToLive=99s", + "zeebe.client.security.certpath=aPath", + "zeebe.client.security.plaintext=true" + } +) +@ContextConfiguration(classes = {CamundaAutoConfiguration.class, ZeebeClientStarterAutoConfigurationCustomZeebeClientManagedChannelFactoryTest.TestConfig.class}) +public class ZeebeClientStarterAutoConfigurationCustomZeebeClientManagedChannelFactoryTest { + + public static class TestConfig { + @Bean + public ObjectMapper objectMapper() { + return new ObjectMapper(); + } + + @Bean + public ZeebeClientManagedChannelFactory customZeebeChannelFactory() { + return new TestZeebeClientManagedChannelFactory(); + } + + private static class TestZeebeClientManagedChannelFactory implements ZeebeClientManagedChannelFactory { + @Override + public ManagedChannel createChannel(ZeebeClientConfigurationProperties configurationProperties) { + return ZeebeClientImpl.buildChannel(configurationProperties); + } + } + } + + @Autowired + private JsonMapper jsonMapper; + @Autowired + private ZeebeClientProdAutoConfiguration autoConfiguration; + @Autowired + private ApplicationContext applicationContext; + @Autowired + private ZeebeClient zeebeClient; + @Autowired + private ZeebeClientManagedChannelFactory zeebeClientManagedChannelFactory;///// + + + @Test + void getJsonMapper() { + assertThat(jsonMapper).isNotNull(); + assertThat(autoConfiguration).isNotNull(); + assertThat(zeebeClient).isNotNull(); + assertThat(zeebeClientManagedChannelFactory).isNotNull(); + assertThat(zeebeClientManagedChannelFactory).isInstanceOf(TestConfig.TestZeebeClientManagedChannelFactory.class); + Map jsonMapperBeans = applicationContext.getBeansOfType(JsonMapper.class); + Object objectMapper = ReflectionTestUtils.getField(jsonMapper, "objectMapper"); + + assertThat(jsonMapperBeans.size()).isEqualTo(1); + assertThat(jsonMapperBeans.containsKey("zeebeJsonMapper")).isTrue(); + assertThat(jsonMapperBeans.get("zeebeJsonMapper")).isSameAs(jsonMapper); + assertThat(objectMapper).isNotNull(); + assertThat(objectMapper).isInstanceOf(ObjectMapper.class); + assertThat(((ObjectMapper) objectMapper).getDeserializationConfig()).isNotNull(); + assertThat(((ObjectMapper) objectMapper).getDeserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES)).isFalse(); + assertThat(((ObjectMapper) objectMapper).getDeserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)).isFalse(); + } + +} diff --git a/spring-boot-starter-camunda/src/test/java/io/camunda/zeebe/spring/client/config/ZeebeClientStarterAutoConfigurationTest.java b/spring-boot-starter-camunda/src/test/java/io/camunda/zeebe/spring/client/config/ZeebeClientStarterAutoConfigurationTest.java index 737ff91c5..7870231bb 100644 --- a/spring-boot-starter-camunda/src/test/java/io/camunda/zeebe/spring/client/config/ZeebeClientStarterAutoConfigurationTest.java +++ b/spring-boot-starter-camunda/src/test/java/io/camunda/zeebe/spring/client/config/ZeebeClientStarterAutoConfigurationTest.java @@ -2,8 +2,11 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import io.camunda.zeebe.client.ZeebeClient; import io.camunda.zeebe.client.api.JsonMapper; import io.camunda.zeebe.spring.client.CamundaAutoConfiguration; +import io.camunda.zeebe.spring.client.configuration.ZeebeClientAllAutoConfiguration; +import io.camunda.zeebe.spring.client.configuration.ZeebeClientManagedChannelFactory; import io.camunda.zeebe.spring.client.configuration.ZeebeClientProdAutoConfiguration; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -40,12 +43,10 @@ public class ZeebeClientStarterAutoConfigurationTest { public static class TestConfig { - @Bean public ObjectMapper objectMapper() { return new ObjectMapper(); } - } @Autowired @@ -54,12 +55,19 @@ public ObjectMapper objectMapper() { private ZeebeClientProdAutoConfiguration autoConfiguration; @Autowired private ApplicationContext applicationContext; + @Autowired + private ZeebeClient zeebeClient; + @Autowired + private ZeebeClientManagedChannelFactory zeebeClientManagedChannelFactory;///// + @Test void getJsonMapper() { assertThat(jsonMapper).isNotNull(); assertThat(autoConfiguration).isNotNull(); - + assertThat(zeebeClient).isNotNull(); + assertThat(zeebeClientManagedChannelFactory).isNotNull(); + assertThat(zeebeClientManagedChannelFactory).isInstanceOf(ZeebeClientAllAutoConfiguration.DefaultZeebeClientManagedChannelFactory.class); Map jsonMapperBeans = applicationContext.getBeansOfType(JsonMapper.class); Object objectMapper = ReflectionTestUtils.getField(jsonMapper, "objectMapper"); @@ -68,9 +76,9 @@ void getJsonMapper() { assertThat(jsonMapperBeans.get("zeebeJsonMapper")).isSameAs(jsonMapper); assertThat(objectMapper).isNotNull(); assertThat(objectMapper).isInstanceOf(ObjectMapper.class); - assertThat(((ObjectMapper)objectMapper).getDeserializationConfig()).isNotNull(); - assertThat(((ObjectMapper)objectMapper).getDeserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES)).isFalse(); - assertThat(((ObjectMapper)objectMapper).getDeserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)).isFalse(); + assertThat(((ObjectMapper) objectMapper).getDeserializationConfig()).isNotNull(); + assertThat(((ObjectMapper) objectMapper).getDeserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES)).isFalse(); + assertThat(((ObjectMapper) objectMapper).getDeserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)).isFalse(); } }