diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/cosmos/AzureCosmosAutoConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/cosmos/AzureCosmosAutoConfiguration.java index c5b09a30c5f7..2b725965744d 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/cosmos/AzureCosmosAutoConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/cosmos/AzureCosmosAutoConfiguration.java @@ -4,8 +4,6 @@ package com.azure.spring.cloud.autoconfigure.implementation.cosmos; import com.azure.cosmos.CosmosClientBuilder; -import com.azure.spring.cloud.autoconfigure.implementation.AzureServiceConfigurationBase; -import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties; import com.azure.spring.cloud.autoconfigure.implementation.cosmos.properties.AzureCosmosPropertiesConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -21,9 +19,5 @@ CosmosClientConfiguration.class }) @ConditionalOnClass(CosmosClientBuilder.class) -public class AzureCosmosAutoConfiguration extends AzureServiceConfigurationBase { - - protected AzureCosmosAutoConfiguration(AzureGlobalProperties azureProperties) { - super(azureProperties); - } +public class AzureCosmosAutoConfiguration { } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureBlobCheckpointStoreConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureBlobCheckpointStoreConfiguration.java index 16fd2746bb4d..48ce309d0e8d 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureBlobCheckpointStoreConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureBlobCheckpointStoreConfiguration.java @@ -16,6 +16,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -32,6 +33,7 @@ */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ BlobCheckpointStore.class, EventHubClientBuilder.class}) +@ConditionalOnBean(AzureEventHubsProperties.class) @ConditionalOnProperty(prefix = "spring.cloud.azure.eventhubs.processor.checkpoint-store", name = { "container-name", "account-name" }) class AzureBlobCheckpointStoreConfiguration { diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsAutoConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsAutoConfiguration.java index 13aef3712767..20bef7bf3721 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsAutoConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsAutoConfiguration.java @@ -4,20 +4,10 @@ package com.azure.spring.cloud.autoconfigure.implementation.eventhubs; import com.azure.messaging.eventhubs.EventHubClientBuilder; -import com.azure.spring.cloud.autoconfigure.implementation.AzureServiceConfigurationBase; -import com.azure.spring.cloud.autoconfigure.implementation.condition.ConditionalOnAnyProperty; -import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties; -import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsProperties; -import com.azure.spring.cloud.core.provider.connectionstring.ServiceConnectionStringProvider; -import com.azure.spring.cloud.core.provider.connectionstring.StaticConnectionStringProvider; -import com.azure.spring.cloud.core.service.AzureServiceType; +import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsPropertiesConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; /** @@ -27,33 +17,14 @@ */ @ConditionalOnClass(EventHubClientBuilder.class) @ConditionalOnProperty(value = "spring.cloud.azure.eventhubs.enabled", havingValue = "true", matchIfMissing = true) -@ConditionalOnAnyProperty(prefix = "spring.cloud.azure.eventhubs", name = { "connection-string", "namespace" }) @Import({ + AzureEventHubsPropertiesConfiguration.class, AzureEventHubsClientBuilderConfiguration.class, AzureEventHubsConsumerClientConfiguration.class, AzureEventHubsProducerClientConfiguration.class, AzureBlobCheckpointStoreConfiguration.class, AzureEventHubsProcessorClientConfiguration.class }) -public class AzureEventHubsAutoConfiguration extends AzureServiceConfigurationBase { - - AzureEventHubsAutoConfiguration(AzureGlobalProperties azureGlobalProperties) { - super(azureGlobalProperties); - } - - @Bean - @ConfigurationProperties(AzureEventHubsProperties.PREFIX) - AzureEventHubsProperties azureEventHubsProperties() { - return loadProperties(getAzureGlobalProperties(), new AzureEventHubsProperties()); - } - - @Bean - @ConditionalOnExpression("'${spring.cloud.azure.eventhubs.connection-string:}' != ''") - @ConditionalOnMissingBean(value = AzureServiceType.EventHubs.class, parameterizedContainer = ServiceConnectionStringProvider.class) - StaticConnectionStringProvider eventHubsStaticConnectionStringProvider( - AzureEventHubsProperties eventHubsProperties) { - return new StaticConnectionStringProvider<>(AzureServiceType.EVENT_HUBS, - eventHubsProperties.getConnectionString()); - } +public class AzureEventHubsAutoConfiguration { } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsClientBuilderConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsClientBuilderConfiguration.java index 9f4471b9fe0c..43f98426b7ea 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsClientBuilderConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsClientBuilderConfiguration.java @@ -4,18 +4,23 @@ package com.azure.spring.cloud.autoconfigure.implementation.eventhubs; import com.azure.messaging.eventhubs.EventHubClientBuilder; -import com.azure.spring.cloud.autoconfigure.implementation.condition.ConditionalOnAnyProperty; +import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsConnectionDetails; import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsProperties; +import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsPropertiesConfiguration; import com.azure.spring.cloud.core.customizer.AzureServiceClientBuilderCustomizer; import com.azure.spring.cloud.core.implementation.util.AzureSpringIdentifier; import com.azure.spring.cloud.core.provider.connectionstring.ServiceConnectionStringProvider; +import com.azure.spring.cloud.core.provider.connectionstring.StaticConnectionStringProvider; import com.azure.spring.cloud.core.service.AzureServiceType; import com.azure.spring.cloud.service.implementation.eventhubs.factory.EventHubClientBuilderFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import static com.azure.spring.cloud.autoconfigure.implementation.context.AzureContextUtils.EVENT_HUB_CLIENT_BUILDER_FACTORY_BEAN_NAME; @@ -24,9 +29,16 @@ * */ @Configuration(proxyBeanMethods = false) -@ConditionalOnAnyProperty(prefix = "spring.cloud.azure.eventhubs", name = { "connection-string", "namespace" }) +@Import(AzureEventHubsPropertiesConfiguration.class) +@ConditionalOnBean(AzureEventHubsProperties.class) class AzureEventHubsClientBuilderConfiguration { + private final AzureEventHubsProperties eventHubsProperties; + + AzureEventHubsClientBuilderConfiguration(AzureEventHubsProperties eventHubsProperties) { + this.eventHubsProperties = eventHubsProperties; + } + @Bean @ConditionalOnMissingBean EventHubClientBuilder eventHubClientBuilder(@Qualifier(EVENT_HUB_CLIENT_BUILDER_FACTORY_BEAN_NAME) @@ -36,10 +48,10 @@ EventHubClientBuilder eventHubClientBuilder(@Qualifier(EVENT_HUB_CLIENT_BUILDER_ @Bean(EVENT_HUB_CLIENT_BUILDER_FACTORY_BEAN_NAME) @ConditionalOnMissingBean - EventHubClientBuilderFactory eventHubClientBuilderFactory(AzureEventHubsProperties properties, + EventHubClientBuilderFactory eventHubClientBuilderFactory( ObjectProvider> connectionStringProviders, ObjectProvider> customizers) { - final EventHubClientBuilderFactory factory = new EventHubClientBuilderFactory(properties); + final EventHubClientBuilderFactory factory = new EventHubClientBuilderFactory(this.eventHubsProperties); factory.setSpringIdentifier(AzureSpringIdentifier.AZURE_SPRING_EVENT_HUBS); connectionStringProviders.orderedStream().findFirst().ifPresent(factory::setConnectionStringProvider); @@ -47,4 +59,21 @@ EventHubClientBuilderFactory eventHubClientBuilderFactory(AzureEventHubsProperti return factory; } + @Bean + @ConditionalOnExpression("'${spring.cloud.azure.eventhubs.connection-string:}' != ''") + @ConditionalOnMissingBean(value = AzureServiceType.EventHubs.class, parameterizedContainer = ServiceConnectionStringProvider.class) + StaticConnectionStringProvider eventHubsStaticConnectionStringProvider() { + return new StaticConnectionStringProvider<>(AzureServiceType.EVENT_HUBS, + this.eventHubsProperties.getConnectionString()); + } + + @Bean + @ConditionalOnBean(AzureEventHubsConnectionDetails.class) + @ConditionalOnMissingBean(value = AzureServiceType.EventHubs.class, parameterizedContainer = ServiceConnectionStringProvider.class) + StaticConnectionStringProvider eventHubsConnectionDetailsStaticConnectionStringProvider( + AzureEventHubsConnectionDetails connectionDetails) { + return new StaticConnectionStringProvider<>(AzureServiceType.EVENT_HUBS, + connectionDetails.getConnectionString()); + } + } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsConsumerClientConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsConsumerClientConfiguration.java index a7fd2cbd2b76..0307e335558f 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsConsumerClientConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsConsumerClientConfiguration.java @@ -38,11 +38,11 @@ AzureEventHubsConsumerClientConfiguration.SharedConsumerConnectionConfiguration.class }) @ConditionalOnAnyProperty(prefix = "spring.cloud.azure.eventhubs", name = { "event-hub-name", "consumer.event-hub-name" }) +@ConditionalOnBean(AzureEventHubsProperties.class) @ConditionalOnProperty(prefix = "spring.cloud.azure.eventhubs.consumer", name = "consumer-group") class AzureEventHubsConsumerClientConfiguration { @ConditionalOnMissingProperty(prefix = "spring.cloud.azure.eventhubs.consumer", name = { "connection-string", "namespace" }) - @ConditionalOnAnyProperty(prefix = "spring.cloud.azure.eventhubs", name = { "connection-string", "namespace" }) @ConditionalOnBean(EventHubClientBuilder.class) @Configuration(proxyBeanMethods = false) static class SharedConsumerConnectionConfiguration { diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsMessagingAutoConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsMessagingAutoConfiguration.java index 24e33d671c62..abd965fbb8d0 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsMessagingAutoConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsMessagingAutoConfiguration.java @@ -6,7 +6,6 @@ import com.azure.core.credential.TokenCredential; import com.azure.messaging.eventhubs.CheckpointStore; import com.azure.messaging.eventhubs.EventData; -import com.azure.spring.cloud.autoconfigure.implementation.condition.ConditionalOnAnyProperty; import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsProperties; import com.azure.spring.cloud.core.implementation.credential.resolver.AzureTokenCredentialResolver; import com.azure.spring.cloud.core.provider.connectionstring.ServiceConnectionStringProvider; @@ -53,7 +52,6 @@ @ConditionalOnClass(EventHubsTemplate.class) @AutoConfigureAfter(AzureEventHubsAutoConfiguration.class) @ConditionalOnProperty(value = "spring.cloud.azure.eventhubs.enabled", havingValue = "true", matchIfMissing = true) -@ConditionalOnAnyProperty(prefix = "spring.cloud.azure.eventhubs", name = {"connection-string", "namespace"}) @ConditionalOnBean(AzureEventHubsProperties.class) @Import({ AzureEventHubsMessagingAutoConfiguration.EventHubsTemplateConfiguration.class, diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsProcessorClientConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsProcessorClientConfiguration.java index 75464f665054..3ec7c9426572 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsProcessorClientConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsProcessorClientConfiguration.java @@ -33,7 +33,7 @@ */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(EventProcessorClientBuilder.class) -@ConditionalOnBean({ MessageListener.class, CheckpointStore.class, EventHubsErrorHandler.class }) +@ConditionalOnBean({ MessageListener.class, CheckpointStore.class, EventHubsErrorHandler.class, AzureEventHubsProperties.class }) @Conditional(AzureEventHubsProcessorClientConfiguration.ProcessorAvailableCondition.class) class AzureEventHubsProcessorClientConfiguration { @@ -119,12 +119,5 @@ static class ConsumerGroup { ConsumerGroup() { } } - - @ConditionalOnAnyProperty( - prefix = "spring.cloud.azure.eventhubs", - name = { "namespace", "connection-string", "processor.namespace", "processor.connection-string" }) - static class ConnectionInfo { - - } } } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsProducerClientConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsProducerClientConfiguration.java index 25a6bca7d4c8..5e5cae605531 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsProducerClientConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsProducerClientConfiguration.java @@ -30,11 +30,11 @@ * */ @Configuration(proxyBeanMethods = false) +@ConditionalOnBean(AzureEventHubsProperties.class) @ConditionalOnAnyProperty(prefix = "spring.cloud.azure.eventhubs", name = { "event-hub-name", "producer.event-hub-name" }) class AzureEventHubsProducerClientConfiguration { @ConditionalOnMissingProperty(prefix = "spring.cloud.azure.eventhubs.producer", name = { "connection-string", "namespace" }) - @ConditionalOnAnyProperty(prefix = "spring.cloud.azure.eventhubs", name = { "connection-string", "namespace" }) @ConditionalOnBean(EventHubClientBuilder.class) @Configuration(proxyBeanMethods = false) static class SharedProducerConnectionConfiguration { diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/kafka/AzureEventHubsKafkaAutoConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/kafka/AzureEventHubsKafkaAutoConfiguration.java index ed73cf8d4337..d018ef936afa 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/kafka/AzureEventHubsKafkaAutoConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/kafka/AzureEventHubsKafkaAutoConfiguration.java @@ -4,6 +4,7 @@ package com.azure.spring.cloud.autoconfigure.implementation.eventhubs.kafka; import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.AzureEventHubsAutoConfiguration; +import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsConnectionDetails; import com.azure.spring.cloud.autoconfigure.implementation.kafka.AzureEventHubsKafkaOAuth2AutoConfiguration; import com.azure.spring.cloud.autoconfigure.implementation.resourcemanager.AzureEventHubsResourceManagerAutoConfiguration; import com.azure.spring.cloud.core.implementation.connectionstring.EventHubsConnectionString; @@ -56,6 +57,23 @@ StaticConnectionStringProvider eventHubsKafkaConnect return new StaticConnectionStringProvider<>(AzureServiceType.EVENT_HUBS, connectionString); } + @Bean + @ConditionalOnBean(AzureEventHubsConnectionDetails.class) + @ConditionalOnMissingBean(value = AzureServiceType.EventHubs.class, parameterizedContainer = ServiceConnectionStringProvider.class) + StaticConnectionStringProvider eventHubsKafkaConnectionDetailsConnectionString( + AzureEventHubsConnectionDetails connectionDetails) { + + String connectionString = connectionDetails.getConnectionString(); + try { + new EventHubsConnectionString(connectionString); + } catch (Exception e) { + LOGGER.error("A valid Event Hubs connection string must be provided"); + throw e; + } + + return new StaticConnectionStringProvider<>(AzureServiceType.EVENT_HUBS, connectionString); + } + @Bean @ConditionalOnBean(value = AzureServiceType.EventHubs.class, parameterizedContainer = ServiceConnectionStringProvider.class) static KafkaPropertiesBeanPostProcessor kafkaPropertiesBeanPostProcessor() { diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/properties/AzureEventHubsConnectionDetails.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/properties/AzureEventHubsConnectionDetails.java new file mode 100644 index 000000000000..9d68aa05b60e --- /dev/null +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/properties/AzureEventHubsConnectionDetails.java @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties; + +import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails; + +public interface AzureEventHubsConnectionDetails extends ConnectionDetails { + + String getConnectionString(); + +} diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/properties/AzureEventHubsPropertiesConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/properties/AzureEventHubsPropertiesConfiguration.java new file mode 100644 index 000000000000..b44c3ba37eb2 --- /dev/null +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/properties/AzureEventHubsPropertiesConfiguration.java @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Import; + +@Import({ + ConfigurationWithConnectionDetailsBean.class, + ConfigurationWithoutConnectionDetailsBean.class, +}) +@EnableConfigurationProperties +public class AzureEventHubsPropertiesConfiguration { +} diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/properties/ConfigurationWithConnectionDetailsBean.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/properties/ConfigurationWithConnectionDetailsBean.java new file mode 100644 index 000000000000..7eeea4a62f26 --- /dev/null +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/properties/ConfigurationWithConnectionDetailsBean.java @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties; + +import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties; +import com.azure.spring.cloud.autoconfigure.implementation.properties.utils.AzureGlobalPropertiesUtils; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails; +import org.springframework.boot.context.properties.bind.BindResult; +import org.springframework.boot.context.properties.bind.Bindable; +import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.context.annotation.Bean; +import org.springframework.core.env.Environment; + +@ConditionalOnClass(ConnectionDetails.class) +@ConditionalOnBean(AzureEventHubsConnectionDetails.class) +class ConfigurationWithConnectionDetailsBean { + + private final Environment environment; + private final AzureGlobalProperties globalProperties; + private final AzureEventHubsConnectionDetails connectionDetails; + + ConfigurationWithConnectionDetailsBean( + Environment environment, + AzureGlobalProperties globalProperties, + AzureEventHubsConnectionDetails connectionDetails) { + this.environment = environment; + this.globalProperties = globalProperties; + this.connectionDetails = connectionDetails; + } + + @Bean + AzureEventHubsProperties azureEventHubsProperties() { + AzureEventHubsProperties propertiesLoadFromGlobalProperties = + AzureGlobalPropertiesUtils.loadProperties(globalProperties, new AzureEventHubsProperties()); + BindResult bindResult = Binder.get(environment) + .bind(AzureEventHubsProperties.PREFIX, Bindable.ofInstance(propertiesLoadFromGlobalProperties)); + AzureEventHubsProperties properties = bindResult.isBound() ? bindResult.get() + : propertiesLoadFromGlobalProperties; + properties.setConnectionString(connectionDetails.getConnectionString()); + return properties; + } + +} diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/properties/ConfigurationWithoutConnectionDetailsBean.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/properties/ConfigurationWithoutConnectionDetailsBean.java new file mode 100644 index 000000000000..9e0dbc1537c2 --- /dev/null +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/properties/ConfigurationWithoutConnectionDetailsBean.java @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties; + +import com.azure.spring.cloud.autoconfigure.implementation.condition.ConditionalOnAnyProperty; +import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties; +import com.azure.spring.cloud.autoconfigure.implementation.properties.utils.AzureGlobalPropertiesUtils; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; + +@ConditionalOnMissingBean(type = "com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsConnectionDetails") +@ConditionalOnProperty(value = "spring.cloud.azure.eventhubs.enabled", havingValue = "true", matchIfMissing = true) +@ConditionalOnAnyProperty(prefix = "spring.cloud.azure.eventhubs", name = {"connection-string", "namespace"}) +class ConfigurationWithoutConnectionDetailsBean { + + private final AzureGlobalProperties azureGlobalProperties; + + ConfigurationWithoutConnectionDetailsBean(AzureGlobalProperties azureGlobalProperties) { + this.azureGlobalProperties = azureGlobalProperties; + } + + @Bean + @ConditionalOnMissingBean + @ConfigurationProperties(AzureEventHubsProperties.PREFIX) + AzureEventHubsProperties azureEventHubsProperties() { + return AzureGlobalPropertiesUtils.loadProperties(azureGlobalProperties, new AzureEventHubsProperties()); + } + +} diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusAutoConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusAutoConfiguration.java index 05ee2da18780..597cfed54acc 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusAutoConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusAutoConfiguration.java @@ -4,8 +4,6 @@ package com.azure.spring.cloud.autoconfigure.implementation.servicebus; import com.azure.messaging.servicebus.ServiceBusClientBuilder; -import com.azure.spring.cloud.autoconfigure.implementation.AzureServiceConfigurationBase; -import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties; import com.azure.spring.cloud.autoconfigure.implementation.servicebus.properties.AzureServiceBusPropertiesConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -26,10 +24,6 @@ AzureServiceBusConsumerClientConfiguration.class, AzureServiceBusProcessorClientConfiguration.class }) -public class AzureServiceBusAutoConfiguration extends AzureServiceConfigurationBase { - - AzureServiceBusAutoConfiguration(AzureGlobalProperties azureGlobalProperties) { - super(azureGlobalProperties); - } +public class AzureServiceBusAutoConfiguration { } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusClientBuilderConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusClientBuilderConfiguration.java index 9002f082e0c6..166d6a6593d4 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusClientBuilderConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusClientBuilderConfiguration.java @@ -4,6 +4,7 @@ package com.azure.spring.cloud.autoconfigure.implementation.servicebus; import com.azure.messaging.servicebus.ServiceBusClientBuilder; +import com.azure.spring.cloud.autoconfigure.implementation.servicebus.properties.AzureServiceBusConnectionDetails; import com.azure.spring.cloud.autoconfigure.implementation.servicebus.properties.AzureServiceBusProperties; import com.azure.spring.cloud.autoconfigure.implementation.servicebus.properties.AzureServiceBusPropertiesConfiguration; import com.azure.spring.cloud.core.customizer.AzureServiceClientBuilderCustomizer; @@ -62,4 +63,14 @@ StaticConnectionStringProvider staticServiceBusConn this.serviceBusProperties.getConnectionString()); } + @Bean + @ConditionalOnBean(AzureServiceBusConnectionDetails.class) + @ConditionalOnMissingBean(value = AzureServiceType.ServiceBus.class, parameterizedContainer = ServiceConnectionStringProvider.class) + StaticConnectionStringProvider staticServiceBusConnectionDetailsConnectionStringProvider( + AzureServiceBusConnectionDetails connectionDetails) { + + return new StaticConnectionStringProvider<>(AzureServiceType.SERVICE_BUS, + connectionDetails.getConnectionString()); + } + } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsAutoConfigurationTests.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsAutoConfigurationTests.java index 367ac4cdb26e..3a81ac24420a 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsAutoConfigurationTests.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsAutoConfigurationTests.java @@ -75,7 +75,7 @@ void configureWithEventHubDisabled() { void configureWithoutConnectionStringAndNamespace() { this.contextRunner .withPropertyValues("spring.cloud.azure.eventhubs.enabled=true") - .run(context -> assertThat(context).doesNotHaveBean(AzureEventHubsAutoConfiguration.class)); + .run(context -> assertThat(context).doesNotHaveBean(AzureEventHubsProperties.class)); } @Test @@ -280,4 +280,20 @@ void configurationPropertiesShouldBind() { }); } + @Test + void connectionDetailsOverridesPropertyConnectionString() { + String connectionString = String.format(CONNECTION_STRING_FORMAT, "test-namespace"); + this.contextRunner + .withPropertyValues( + "spring.cloud.azure.eventhubs.connection-string=" + connectionString + ) + .withBean(AzureGlobalProperties.class, AzureGlobalProperties::new) + .withBean(com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsConnectionDetails.class, CustomAzureEventHubsConnectionDetails::new) + .run(context -> { + assertThat(context).hasSingleBean(AzureEventHubsProperties.class); + AzureEventHubsProperties properties = context.getBean(AzureEventHubsProperties.class); + assertEquals(CustomAzureEventHubsConnectionDetails.CONNECTION_STRING, properties.getConnectionString()); + }); + } + } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsClientBuilderConfigurationTests.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsClientBuilderConfigurationTests.java index d4b92480a714..62d554eb6741 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsClientBuilderConfigurationTests.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsClientBuilderConfigurationTests.java @@ -6,6 +6,9 @@ import com.azure.data.appconfiguration.ConfigurationClientBuilder; import com.azure.messaging.eventhubs.EventHubClientBuilder; import com.azure.spring.cloud.autoconfigure.implementation.TestBuilderCustomizer; +import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties; +import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsConnectionDetails; +import com.azure.spring.cloud.core.provider.connectionstring.StaticConnectionStringProvider; import com.azure.spring.cloud.service.implementation.eventhubs.factory.EventHubClientBuilderFactory; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -17,7 +20,7 @@ class AzureEventHubsClientBuilderConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(AzureEventHubsClientBuilderConfiguration.class)); + .withConfiguration(AutoConfigurations.of(AzureEventHubsAutoConfiguration.class)); @Test void noConnectionInfoProvidedShouldNotConfigure() { @@ -30,7 +33,7 @@ void connectionStringProvidedShouldConfigure() { .withPropertyValues( "spring.cloud.azure.eventhubs.connection-string=" + String.format(CONNECTION_STRING_FORMAT, "test-namespace") ) - .withUserConfiguration(AzureEventHubsPropertiesTestConfiguration.class) + .withBean(AzureGlobalProperties.class, AzureGlobalProperties::new) .run(context -> { assertThat(context).hasSingleBean(AzureEventHubsClientBuilderConfiguration.class); assertThat(context).hasSingleBean(EventHubClientBuilderFactory.class); @@ -44,7 +47,7 @@ void namespaceProvidedShouldConfigure() { .withPropertyValues( "spring.cloud.azure.eventhubs.namespace=test-namespace" ) - .withUserConfiguration(AzureEventHubsPropertiesTestConfiguration.class) + .withBean(AzureGlobalProperties.class, AzureGlobalProperties::new) .run(context -> { assertThat(context).hasSingleBean(AzureEventHubsClientBuilderConfiguration.class); assertThat(context).hasSingleBean(EventHubClientBuilderFactory.class); @@ -59,7 +62,7 @@ void customizerShouldBeCalled() { .withPropertyValues( "spring.cloud.azure.eventhubs.connection-string=" + String.format(CONNECTION_STRING_FORMAT, "test-namespace") ) - .withUserConfiguration(AzureEventHubsPropertiesTestConfiguration.class) + .withBean(AzureGlobalProperties.class, AzureGlobalProperties::new) .withBean("customizer1", EventHubBuilderCustomizer.class, () -> customizer) .withBean("customizer2", EventHubBuilderCustomizer.class, () -> customizer) .run(context -> assertThat(customizer.getCustomizedTimes()).isEqualTo(2)); @@ -73,7 +76,7 @@ void otherCustomizerShouldNotBeCalled() { .withPropertyValues( "spring.cloud.azure.eventhubs.connection-string=" + String.format(CONNECTION_STRING_FORMAT, "test-namespace") ) - .withUserConfiguration(AzureEventHubsPropertiesTestConfiguration.class) + .withBean(AzureGlobalProperties.class, AzureGlobalProperties::new) .withBean("customizer1", EventHubBuilderCustomizer.class, () -> customizer) .withBean("customizer2", EventHubBuilderCustomizer.class, () -> customizer) .withBean("customizer3", OtherBuilderCustomizer.class, () -> otherBuilderCustomizer) @@ -89,7 +92,7 @@ void userDefinedEventHubsClientBuilderProvidedShouldNotAutoconfigure() { .withPropertyValues( "spring.cloud.azure.eventhubs.connection-string=" + String.format(CONNECTION_STRING_FORMAT, "test-namespace") ) - .withUserConfiguration(AzureEventHubsPropertiesTestConfiguration.class) + .withBean(AzureGlobalProperties.class, AzureGlobalProperties::new) .withBean("user-defined-builder", EventHubClientBuilder.class, EventHubClientBuilder::new) .run(context -> { assertThat(context).hasSingleBean(EventHubClientBuilder.class); @@ -97,6 +100,44 @@ void userDefinedEventHubsClientBuilderProvidedShouldNotAutoconfigure() { }); } + @Test + void connectionStringPropertyRegistersStaticProvider() { + String connectionString = String.format(CONNECTION_STRING_FORMAT, "test-namespace"); + this.contextRunner + .withPropertyValues( + "spring.cloud.azure.eventhubs.connection-string=" + connectionString + ) + .withBean(AzureGlobalProperties.class, AzureGlobalProperties::new) + .run(context -> { + assertThat(context).hasSingleBean(StaticConnectionStringProvider.class); + assertThat(context.getBean(StaticConnectionStringProvider.class).getConnectionString()) + .isEqualTo(connectionString); + }); + } + + @Test + void connectionDetailsRegistersStaticProvider() { + String connectionString = String.format(CONNECTION_STRING_FORMAT, "details-namespace"); + this.contextRunner + .withBean(AzureGlobalProperties.class, AzureGlobalProperties::new) + .withBean(AzureEventHubsConnectionDetails.class, () -> new TestConnectionDetails(connectionString)) + .run(context -> { + assertThat(context).hasSingleBean(StaticConnectionStringProvider.class); + assertThat(context.getBean(StaticConnectionStringProvider.class).getConnectionString()) + .isEqualTo(connectionString); + }); + } + + @Test + void namespaceOnlyDoesNotRegisterStaticProvider() { + this.contextRunner + .withPropertyValues( + "spring.cloud.azure.eventhubs.namespace=test-namespace" + ) + .withBean(AzureGlobalProperties.class, AzureGlobalProperties::new) + .run(context -> assertThat(context).doesNotHaveBean(StaticConnectionStringProvider.class)); + } + private static class EventHubBuilderCustomizer extends TestBuilderCustomizer { } @@ -105,4 +146,17 @@ private static class OtherBuilderCustomizer extends TestBuilderCustomizer { assertThat(context).hasSingleBean(AzureEventHubsConsumerClientConfiguration.class); assertThat(context).doesNotHaveBean(AzureEventHubsConsumerClientConfiguration.SharedConsumerConnectionConfiguration.class); @@ -45,6 +46,7 @@ void eventHubNameAndConsumerGroupProvidedShouldConfigure() { "spring.cloud.azure.eventhubs.consumer.event-hub-name=test-eventhub", "spring.cloud.azure.eventhubs.consumer.consumer-group=test-consumer-group" ) + .withUserConfiguration(AzureEventHubsPropertiesTestConfiguration.class) .run(context -> { assertThat(context).hasSingleBean(AzureEventHubsConsumerClientConfiguration.class); assertThat(context).doesNotHaveBean(AzureEventHubsConsumerClientConfiguration.SharedConsumerConnectionConfiguration.class); diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsMessagingAutoConfigurationTests.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsMessagingAutoConfigurationTests.java index 8ae0399acb60..6a5520c546d5 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsMessagingAutoConfigurationTests.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsMessagingAutoConfigurationTests.java @@ -59,7 +59,6 @@ void withoutEventHubsTemplateShouldNotConfigure() { @Test void withoutEventHubConnectionShouldNotConfigure() { this.contextRunner - .withUserConfiguration(AzureEventHubsPropertiesTestConfiguration.class) .withBean(CheckpointStore.class, TestCheckpointStore::new) .run(context -> assertThat(context).doesNotHaveBean(AzureEventHubsMessagingAutoConfiguration.ProcessorContainerConfiguration.class)); } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsProducerClientConfigurationTests.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsProducerClientConfigurationTests.java index d8c4f6147c89..db7361326694 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsProducerClientConfigurationTests.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsProducerClientConfigurationTests.java @@ -33,6 +33,7 @@ void eventHubNameProvidedShouldConfigure() { .withPropertyValues( "spring.cloud.azure.eventhubs.event-hub-name=test-eventhub" ) + .withUserConfiguration(AzureEventHubsPropertiesTestConfiguration.class) .run(context -> { assertThat(context).hasSingleBean(AzureEventHubsProducerClientConfiguration.class); assertThat(context).doesNotHaveBean(AzureEventHubsProducerClientConfiguration.SharedProducerConnectionConfiguration.class); @@ -43,6 +44,7 @@ void eventHubNameProvidedShouldConfigure() { .withPropertyValues( "spring.cloud.azure.eventhubs.producer.event-hub-name=test-eventhub" ) + .withUserConfiguration(AzureEventHubsPropertiesTestConfiguration.class) .run(context -> { assertThat(context).hasSingleBean(AzureEventHubsProducerClientConfiguration.class); assertThat(context).doesNotHaveBean(AzureEventHubsProducerClientConfiguration.SharedProducerConnectionConfiguration.class); @@ -65,6 +67,7 @@ void withGlobalEventHubConnectionSetShouldConfigureShared() { "spring.cloud.azure.eventhubs.namespace=" + namespace, "spring.cloud.azure.eventhubs.event-hub-name=" + eventHubName ) + .withUserConfiguration(AzureEventHubsPropertiesTestConfiguration.class) .withBean(EventHubClientBuilder.class, () -> clientBuilder) .run( context -> { diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/CustomAzureEventHubsConnectionDetails.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/CustomAzureEventHubsConnectionDetails.java new file mode 100644 index 000000000000..d5faa229ef11 --- /dev/null +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/CustomAzureEventHubsConnectionDetails.java @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.autoconfigure.implementation.eventhubs; + +import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsConnectionDetails; + +public class CustomAzureEventHubsConnectionDetails implements AzureEventHubsConnectionDetails { + + static final String CONNECTION_STRING = "Endpoint=sb://connection-detail-namespace.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=test-key;EntityPath=test-eventhub"; + + @Override + public String getConnectionString() { + return CONNECTION_STRING; + } +} diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/kafka/AzureEventHubsKafkaAutoConfigurationTests.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/kafka/AzureEventHubsKafkaAutoConfigurationTests.java new file mode 100644 index 000000000000..80eb3d7a561b --- /dev/null +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/kafka/AzureEventHubsKafkaAutoConfigurationTests.java @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.autoconfigure.implementation.eventhubs.kafka; + +import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties; +import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.AzureEventHubsAutoConfiguration; +import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsConnectionDetails; +import com.azure.spring.cloud.autoconfigure.implementation.kafka.AzureEventHubsKafkaOAuth2AutoConfiguration; +import com.azure.spring.cloud.core.provider.connectionstring.StaticConnectionStringProvider; +import com.azure.spring.cloud.core.service.AzureServiceType; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@SuppressWarnings("deprecation") +class AzureEventHubsKafkaAutoConfigurationTests { + + private static final String CONNECTION_STRING = "Endpoint=sb://test-namespace.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=key"; + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of( + AzureEventHubsAutoConfiguration.class, + AzureEventHubsKafkaAutoConfiguration.class, + AzureEventHubsKafkaOAuth2AutoConfiguration.class)) + .withBean(AzureGlobalProperties.class, AzureGlobalProperties::new); + + @Test + void connectionStringRegistersProvider() { + this.contextRunner + .withPropertyValues( + "spring.cloud.azure.eventhubs.connection-string=" + CONNECTION_STRING + ) + .run(context -> { + assertThat(context).hasSingleBean(StaticConnectionStringProvider.class); + StaticConnectionStringProvider provider = context.getBean(StaticConnectionStringProvider.class); + assertThat(provider.getServiceType()).isEqualTo(AzureServiceType.EVENT_HUBS); + assertThat(provider.getConnectionString()).isEqualTo(CONNECTION_STRING); + }); + } + + @Test + void connectionDetailsRegistersProvider() { + this.contextRunner + .withBean(AzureEventHubsConnectionDetails.class, () -> () -> CONNECTION_STRING) + .run(context -> { + assertThat(context).hasSingleBean(StaticConnectionStringProvider.class); + StaticConnectionStringProvider provider = context.getBean(StaticConnectionStringProvider.class); + assertThat(provider.getServiceType()).isEqualTo(AzureServiceType.EVENT_HUBS); + assertThat(provider.getConnectionString()).isEqualTo(CONNECTION_STRING); + }); + } + + @Test + void namespaceOnlyDoesNotRegisterProvider() { + this.contextRunner + .withPropertyValues("spring.cloud.azure.eventhubs.namespace=test-namespace") + .run(context -> assertThat(context).doesNotHaveBean(StaticConnectionStringProvider.class)); + } +} diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusClientBuilderConfigurationTests.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusClientBuilderConfigurationTests.java index 83c1f2d1ed47..cde00bb3389c 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusClientBuilderConfigurationTests.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusClientBuilderConfigurationTests.java @@ -7,6 +7,7 @@ import com.azure.messaging.servicebus.ServiceBusClientBuilder; import com.azure.spring.cloud.autoconfigure.implementation.TestBuilderCustomizer; import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties; +import com.azure.spring.cloud.autoconfigure.implementation.servicebus.properties.AzureServiceBusConnectionDetails; import com.azure.spring.cloud.autoconfigure.implementation.servicebus.properties.AzureServiceBusProperties; import com.azure.spring.cloud.core.provider.connectionstring.StaticConnectionStringProvider; import com.azure.spring.cloud.core.service.AzureServiceType; @@ -31,7 +32,7 @@ void noConnectionInfoProvidedShouldNotConfigure() { } @Test - @SuppressWarnings("rawtypes") + @SuppressWarnings({"rawtypes", "unchecked"}) void connectionStringProvidedShouldConfigure() { contextRunner .withPropertyValues( @@ -89,6 +90,20 @@ void configureWithNamespaceAndEmptyConnectionString() { }); } + @Test + @SuppressWarnings({"rawtypes", "unchecked"}) + void connectionDetailsRegistersStaticProvider() { + String connectionString = String.format(CONNECTION_STRING_FORMAT, "details-namespace"); + this.contextRunner + .withBean(AzureServiceBusConnectionDetails.class, () -> new TestConnectionDetails(connectionString)) + .run(context -> { + assertThat(context).hasSingleBean(StaticConnectionStringProvider.class); + StaticConnectionStringProvider provider = context.getBean(StaticConnectionStringProvider.class); + assertThat(provider.getConnectionString()).isEqualTo(connectionString); + assertThat(provider.getServiceType()).isEqualTo(AzureServiceType.SERVICE_BUS); + }); + } + private static class ServiceBusBuilderCustomizer extends TestBuilderCustomizer { } @@ -97,4 +112,17 @@ private static class OtherBuilderCustomizer extends TestBuilderCustomizer12.28.1 true - - com.azure - azure-messaging-servicebus - 7.17.17 - true - org.springframework.boot @@ -104,6 +98,18 @@ provided + + com.azure + azure-messaging-servicebus + 7.17.17 + test + + + com.azure + azure-messaging-eventhubs + 5.21.3 + test + com.azure.spring spring-messaging-azure-servicebus diff --git a/sdk/spring/spring-cloud-azure-docker-compose/src/main/java/com/azure/spring/cloud/docker/compose/implementation/service/connection/hubs/EventHubsDockerComposeConnectionDetailsFactory.java b/sdk/spring/spring-cloud-azure-docker-compose/src/main/java/com/azure/spring/cloud/docker/compose/implementation/service/connection/hubs/EventHubsDockerComposeConnectionDetailsFactory.java new file mode 100644 index 000000000000..e34128b855f5 --- /dev/null +++ b/sdk/spring/spring-cloud-azure-docker-compose/src/main/java/com/azure/spring/cloud/docker/compose/implementation/service/connection/hubs/EventHubsDockerComposeConnectionDetailsFactory.java @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.docker.compose.implementation.service.connection.hubs; + +import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsConnectionDetails; +import org.springframework.boot.docker.compose.core.RunningService; +import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory; +import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource; + +class EventHubsDockerComposeConnectionDetailsFactory + extends DockerComposeConnectionDetailsFactory { + + private static final int EVENT_HUBS_PORT = 5672; + + protected EventHubsDockerComposeConnectionDetailsFactory() { + super("azure-messaging/eventhubs-emulator"); + } + + @Override + protected AzureEventHubsConnectionDetails getDockerComposeConnectionDetails(DockerComposeConnectionSource source) { + return new EventHubsContainerConnectionDetails(source.getRunningService()); + } + + /** + * {@link AzureEventHubsConnectionDetails} backed by an {@code Event Hubs} + * {@link RunningService}. + */ + private static class EventHubsContainerConnectionDetails extends DockerComposeConnectionDetails + implements AzureEventHubsConnectionDetails { + + private final String host; + + private final int port; + + EventHubsContainerConnectionDetails(RunningService service) { + super(service); + this.host = service.host(); + this.port = service.ports().get(EVENT_HUBS_PORT); + } + + @Override + public String getConnectionString() { + return "Endpoint=sb://%s:%d;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;" + .formatted(this.host, this.port); + } + } +} diff --git a/sdk/spring/spring-cloud-azure-docker-compose/src/main/resources/META-INF/spring.factories b/sdk/spring/spring-cloud-azure-docker-compose/src/main/resources/META-INF/spring.factories index 6de8408e5b64..591a4d528944 100644 --- a/sdk/spring/spring-cloud-azure-docker-compose/src/main/resources/META-INF/spring.factories +++ b/sdk/spring/spring-cloud-azure-docker-compose/src/main/resources/META-INF/spring.factories @@ -1,4 +1,5 @@ org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\ com.azure.spring.cloud.docker.compose.implementation.service.connection.bus.ServiceBusDockerComposeConnectionDetailsFactory,\ com.azure.spring.cloud.docker.compose.implementation.service.connection.storage.StorageBlobDockerComposeConnectionDetailsFactory,\ -com.azure.spring.cloud.docker.compose.implementation.service.connection.storage.StorageQueueDockerComposeConnectionDetailsFactory +com.azure.spring.cloud.docker.compose.implementation.service.connection.storage.StorageQueueDockerComposeConnectionDetailsFactory,\ +com.azure.spring.cloud.docker.compose.implementation.service.connection.hubs.EventHubsDockerComposeConnectionDetailsFactory diff --git a/sdk/spring/spring-cloud-azure-docker-compose/src/test/java/com/azure/spring/cloud/docker/compose/implementation/service/connection/bus/ServiceBusDockerComposeConnectionDetailsFactoryTests.java b/sdk/spring/spring-cloud-azure-docker-compose/src/test/java/com/azure/spring/cloud/docker/compose/implementation/service/connection/bus/ServiceBusDockerComposeConnectionDetailsFactoryTests.java index 9a14f229e914..3f1d51308a7d 100644 --- a/sdk/spring/spring-cloud-azure-docker-compose/src/test/java/com/azure/spring/cloud/docker/compose/implementation/service/connection/bus/ServiceBusDockerComposeConnectionDetailsFactoryTests.java +++ b/sdk/spring/spring-cloud-azure-docker-compose/src/test/java/com/azure/spring/cloud/docker/compose/implementation/service/connection/bus/ServiceBusDockerComposeConnectionDetailsFactoryTests.java @@ -8,6 +8,7 @@ import com.azure.spring.cloud.autoconfigure.implementation.context.AzureGlobalPropertiesAutoConfiguration; import com.azure.spring.cloud.autoconfigure.implementation.servicebus.AzureServiceBusAutoConfiguration; import com.azure.spring.cloud.autoconfigure.implementation.servicebus.AzureServiceBusMessagingAutoConfiguration; +import com.azure.spring.cloud.autoconfigure.implementation.servicebus.properties.AzureServiceBusConnectionDetails; import com.azure.spring.cloud.service.servicebus.consumer.ServiceBusErrorHandler; import com.azure.spring.cloud.service.servicebus.consumer.ServiceBusRecordMessageListener; import com.azure.spring.messaging.servicebus.core.ServiceBusTemplate; @@ -30,8 +31,9 @@ @SpringBootTest(properties = { "spring.docker.compose.skip.in-tests=false", - "spring.docker.compose.file=classpath:com/azure/spring/cloud/docker/compose/implementation/service/connection/servicebus/servicebus-compose.yaml", + "spring.docker.compose.file=classpath:com/azure/spring/cloud/docker/compose/implementation/service/connection/bus/servicebus-compose.yaml", "spring.docker.compose.stop.command=down", + "spring.docker.compose.readiness.timeout=PT5M", "spring.cloud.azure.servicebus.namespace=sbemulatorns", "spring.cloud.azure.servicebus.entity-name=queue.1", "spring.cloud.azure.servicebus.entity-type=queue", @@ -43,12 +45,23 @@ @EnabledOnOs(OS.LINUX) class ServiceBusDockerComposeConnectionDetailsFactoryTests { + @Autowired + private AzureServiceBusConnectionDetails connectionDetails; + @Autowired private ServiceBusSenderClient senderClient; @Autowired private ServiceBusTemplate serviceBusTemplate; + @Test + void connectionDetailsShouldBeProvidedByFactory() { + assertThat(connectionDetails).isNotNull(); + assertThat(connectionDetails.getConnectionString()) + .isNotBlank() + .startsWith("Endpoint=sb://"); + } + @Test void senderClientCanSendMessage() { // Wait for Service Bus emulator to be fully ready and queue entity to be available diff --git a/sdk/spring/spring-cloud-azure-docker-compose/src/test/java/com/azure/spring/cloud/docker/compose/implementation/service/connection/hubs/EventHubsDockerComposeConnectionDetailsFactoryTests.java b/sdk/spring/spring-cloud-azure-docker-compose/src/test/java/com/azure/spring/cloud/docker/compose/implementation/service/connection/hubs/EventHubsDockerComposeConnectionDetailsFactoryTests.java new file mode 100644 index 000000000000..1369301024c1 --- /dev/null +++ b/sdk/spring/spring-cloud-azure-docker-compose/src/test/java/com/azure/spring/cloud/docker/compose/implementation/service/connection/hubs/EventHubsDockerComposeConnectionDetailsFactoryTests.java @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.docker.compose.implementation.service.connection.hubs; + +import com.azure.messaging.eventhubs.EventData; +import com.azure.messaging.eventhubs.EventHubProducerClient; +import com.azure.spring.cloud.autoconfigure.implementation.context.AzureGlobalPropertiesAutoConfiguration; +import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.AzureEventHubsAutoConfiguration; +import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsConnectionDetails; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Configuration; + +import java.time.Duration; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.waitAtMost; + +@SpringBootTest(properties = { + "spring.docker.compose.skip.in-tests=false", + "spring.docker.compose.file=classpath:com/azure/spring/cloud/docker/compose/implementation/service/connection/hubs/eventhubs-compose.yaml", + "spring.docker.compose.stop.command=down", + "spring.docker.compose.readiness.timeout=PT5M", + "spring.cloud.azure.eventhubs.event-hub-name=eh1", + "spring.cloud.azure.eventhubs.producer.event-hub-name=eh1" +}) +@EnabledOnOs(OS.LINUX) +class EventHubsDockerComposeConnectionDetailsFactoryTests { + + @Autowired + private AzureEventHubsConnectionDetails connectionDetails; + + @Autowired + private EventHubProducerClient producerClient; + + @Test + void connectionDetailsShouldBeProvidedByFactory() { + assertThat(connectionDetails).isNotNull(); + assertThat(connectionDetails.getConnectionString()) + .isNotBlank() + .startsWith("Endpoint=sb://"); + } + + @Test + void producerClientCanSendMessage() { + // Wait for Event Hubs emulator to be fully ready and event hub entity to be available + waitAtMost(Duration.ofSeconds(120)).pollInterval(Duration.ofSeconds(2)).untilAsserted(() -> { + EventData event = new EventData("Hello World!"); + this.producerClient.send(Collections.singletonList(event)); + }); + } + + @Configuration(proxyBeanMethods = false) + @ImportAutoConfiguration(classes = { + AzureGlobalPropertiesAutoConfiguration.class, + AzureEventHubsAutoConfiguration.class}) + static class Config { + } +} diff --git a/sdk/spring/spring-cloud-azure-docker-compose/src/test/resources/com/azure/spring/cloud/docker/compose/implementation/service/connection/servicebus/Config.json b/sdk/spring/spring-cloud-azure-docker-compose/src/test/resources/com/azure/spring/cloud/docker/compose/implementation/service/connection/bus/Config.json similarity index 100% rename from sdk/spring/spring-cloud-azure-docker-compose/src/test/resources/com/azure/spring/cloud/docker/compose/implementation/service/connection/servicebus/Config.json rename to sdk/spring/spring-cloud-azure-docker-compose/src/test/resources/com/azure/spring/cloud/docker/compose/implementation/service/connection/bus/Config.json diff --git a/sdk/spring/spring-cloud-azure-docker-compose/src/test/resources/com/azure/spring/cloud/docker/compose/implementation/service/connection/servicebus/servicebus-compose.yaml b/sdk/spring/spring-cloud-azure-docker-compose/src/test/resources/com/azure/spring/cloud/docker/compose/implementation/service/connection/bus/servicebus-compose.yaml similarity index 100% rename from sdk/spring/spring-cloud-azure-docker-compose/src/test/resources/com/azure/spring/cloud/docker/compose/implementation/service/connection/servicebus/servicebus-compose.yaml rename to sdk/spring/spring-cloud-azure-docker-compose/src/test/resources/com/azure/spring/cloud/docker/compose/implementation/service/connection/bus/servicebus-compose.yaml diff --git a/sdk/spring/spring-cloud-azure-docker-compose/src/test/resources/com/azure/spring/cloud/docker/compose/implementation/service/connection/hubs/Config.json b/sdk/spring/spring-cloud-azure-docker-compose/src/test/resources/com/azure/spring/cloud/docker/compose/implementation/service/connection/hubs/Config.json new file mode 100644 index 000000000000..0749990d11d4 --- /dev/null +++ b/sdk/spring/spring-cloud-azure-docker-compose/src/test/resources/com/azure/spring/cloud/docker/compose/implementation/service/connection/hubs/Config.json @@ -0,0 +1,20 @@ +{ + "UserConfig": { + "NamespaceConfig": [ + { + "Type": "EventHub", + "Name": "emulatorns1", + "Entities": [ + { + "Name": "eh1", + "PartitionCount": "2", + "ConsumerGroups": [] + } + ] + } + ], + "LoggingConfig": { + "Type": "File" + } + } +} diff --git a/sdk/spring/spring-cloud-azure-docker-compose/src/test/resources/com/azure/spring/cloud/docker/compose/implementation/service/connection/hubs/eventhubs-compose.yaml b/sdk/spring/spring-cloud-azure-docker-compose/src/test/resources/com/azure/spring/cloud/docker/compose/implementation/service/connection/hubs/eventhubs-compose.yaml new file mode 100644 index 000000000000..6aa1d2d7a0f9 --- /dev/null +++ b/sdk/spring/spring-cloud-azure-docker-compose/src/test/resources/com/azure/spring/cloud/docker/compose/implementation/service/connection/hubs/eventhubs-compose.yaml @@ -0,0 +1,34 @@ +services: + eventhubs: + image: mcr.microsoft.com/azure-messaging/eventhubs-emulator:latest + pull_policy: always + volumes: + # Mount the emulator configuration to the path expected by the emulator image + - "./Config.json:/Eventhubs_Emulator/ConfigFiles/Config.json" + ports: + - "5672" + environment: + # Event Hubs emulator requires external blob/metadata storage provided by azurite + BLOB_SERVER: azurite + METADATA_SERVER: azurite + ACCEPT_EULA: Y + depends_on: + - azurite + networks: + eh-emulator: + aliases: + - "eh-emulator" + + azurite: + image: "mcr.microsoft.com/azure-storage/azurite:latest" + ports: + - "10000" + - "10001" + - "10002" + networks: + eh-emulator: + aliases: + - "azurite" + +networks: + eh-emulator: diff --git a/sdk/spring/spring-cloud-azure-testcontainers/pom.xml b/sdk/spring/spring-cloud-azure-testcontainers/pom.xml index 5a381271d750..84a0148236b9 100644 --- a/sdk/spring/spring-cloud-azure-testcontainers/pom.xml +++ b/sdk/spring/spring-cloud-azure-testcontainers/pom.xml @@ -78,12 +78,6 @@ 12.28.1 true - - com.azure - azure-messaging-servicebus - 7.17.17 - true - com.azure.spring spring-messaging-azure-servicebus @@ -102,12 +96,6 @@ 1.21.3 true - - com.microsoft.sqlserver - mssql-jdbc - 13.2.1.jre11 - true - @@ -118,6 +106,24 @@ provided + + com.azure + azure-messaging-servicebus + 7.17.17 + test + + + com.azure + azure-messaging-eventhubs + 5.21.3 + test + + + com.microsoft.sqlserver + mssql-jdbc + 13.2.1.jre11 + test + org.springframework spring-test diff --git a/sdk/spring/spring-cloud-azure-testcontainers/src/main/java/com/azure/spring/cloud/testcontainers/implementation/service/connection/hubs/EventHubsContainerConnectionDetailsFactory.java b/sdk/spring/spring-cloud-azure-testcontainers/src/main/java/com/azure/spring/cloud/testcontainers/implementation/service/connection/hubs/EventHubsContainerConnectionDetailsFactory.java new file mode 100644 index 000000000000..a3b5460446ef --- /dev/null +++ b/sdk/spring/spring-cloud-azure-testcontainers/src/main/java/com/azure/spring/cloud/testcontainers/implementation/service/connection/hubs/EventHubsContainerConnectionDetailsFactory.java @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.testcontainers.implementation.service.connection.hubs; + +import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsConnectionDetails; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource; +import org.testcontainers.azure.EventHubsEmulatorContainer; + +class EventHubsContainerConnectionDetailsFactory + extends ContainerConnectionDetailsFactory { + + @Override + protected AzureEventHubsConnectionDetails getContainerConnectionDetails(ContainerConnectionSource source) { + return new EventHubsContainerConnectionDetails(source); + } + + /** + * {@link AzureEventHubsConnectionDetails} backed by a {@link ContainerConnectionSource}. + */ + private static class EventHubsContainerConnectionDetails extends ContainerConnectionDetails + implements AzureEventHubsConnectionDetails { + + EventHubsContainerConnectionDetails(ContainerConnectionSource source) { + super(source); + } + + @Override + public String getConnectionString() { + return getContainer().getConnectionString(); + } + } +} diff --git a/sdk/spring/spring-cloud-azure-testcontainers/src/main/resources/META-INF/spring.factories b/sdk/spring/spring-cloud-azure-testcontainers/src/main/resources/META-INF/spring.factories index 8d3008a6217a..a590e8a7e19f 100644 --- a/sdk/spring/spring-cloud-azure-testcontainers/src/main/resources/META-INF/spring.factories +++ b/sdk/spring/spring-cloud-azure-testcontainers/src/main/resources/META-INF/spring.factories @@ -2,4 +2,5 @@ org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFacto com.azure.spring.cloud.testcontainers.implementation.service.connection.cosmos.CosmosContainerConnectionDetailsFactory,\ com.azure.spring.cloud.testcontainers.implementation.service.connection.bus.ServiceBusContainerConnectionDetailsFactory,\ com.azure.spring.cloud.testcontainers.implementation.service.connection.storage.StorageBlobContainerConnectionDetailsFactory,\ -com.azure.spring.cloud.testcontainers.implementation.service.connection.storage.StorageQueueContainerConnectionDetailsFactory +com.azure.spring.cloud.testcontainers.implementation.service.connection.storage.StorageQueueContainerConnectionDetailsFactory,\ +com.azure.spring.cloud.testcontainers.implementation.service.connection.hubs.EventHubsContainerConnectionDetailsFactory diff --git a/sdk/spring/spring-cloud-azure-testcontainers/src/test/java/com/azure/spring/cloud/testcontainers/implementation/service/connection/bus/ServiceBusContainerConnectionDetailsFactoryTests.java b/sdk/spring/spring-cloud-azure-testcontainers/src/test/java/com/azure/spring/cloud/testcontainers/implementation/service/connection/bus/ServiceBusContainerConnectionDetailsFactoryTests.java index 0771ab5da8a4..de67d4779f35 100644 --- a/sdk/spring/spring-cloud-azure-testcontainers/src/test/java/com/azure/spring/cloud/testcontainers/implementation/service/connection/bus/ServiceBusContainerConnectionDetailsFactoryTests.java +++ b/sdk/spring/spring-cloud-azure-testcontainers/src/test/java/com/azure/spring/cloud/testcontainers/implementation/service/connection/bus/ServiceBusContainerConnectionDetailsFactoryTests.java @@ -8,6 +8,7 @@ import com.azure.spring.cloud.autoconfigure.implementation.context.AzureGlobalPropertiesAutoConfiguration; import com.azure.spring.cloud.autoconfigure.implementation.servicebus.AzureServiceBusAutoConfiguration; import com.azure.spring.cloud.autoconfigure.implementation.servicebus.AzureServiceBusMessagingAutoConfiguration; +import com.azure.spring.cloud.autoconfigure.implementation.servicebus.properties.AzureServiceBusConnectionDetails; import com.azure.spring.cloud.service.servicebus.consumer.ServiceBusErrorHandler; import com.azure.spring.cloud.service.servicebus.consumer.ServiceBusRecordMessageListener; import com.azure.spring.messaging.servicebus.core.ServiceBusTemplate; @@ -61,12 +62,23 @@ class ServiceBusContainerConnectionDetailsFactoryTests { .withNetwork(NETWORK) .withMsSqlServerContainer(SQLSERVER); + @Autowired + private AzureServiceBusConnectionDetails connectionDetails; + @Autowired private ServiceBusSenderClient senderClient; @Autowired private ServiceBusTemplate serviceBusTemplate; + @Test + void connectionDetailsShouldBeProvidedByFactory() { + assertThat(connectionDetails).isNotNull(); + assertThat(connectionDetails.getConnectionString()) + .isNotBlank() + .startsWith("Endpoint=sb://"); + } + @Test void senderClientCanSendMessage() { // Wait for Service Bus emulator to be fully ready and queue entity to be available diff --git a/sdk/spring/spring-cloud-azure-testcontainers/src/test/java/com/azure/spring/cloud/testcontainers/implementation/service/connection/hubs/EventHubsContainerConnectionDetailsFactoryTests.java b/sdk/spring/spring-cloud-azure-testcontainers/src/test/java/com/azure/spring/cloud/testcontainers/implementation/service/connection/hubs/EventHubsContainerConnectionDetailsFactoryTests.java new file mode 100644 index 000000000000..84c05c2bc6a2 --- /dev/null +++ b/sdk/spring/spring-cloud-azure-testcontainers/src/test/java/com/azure/spring/cloud/testcontainers/implementation/service/connection/hubs/EventHubsContainerConnectionDetailsFactoryTests.java @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.testcontainers.implementation.service.connection.hubs; + +import com.azure.messaging.eventhubs.EventData; +import com.azure.messaging.eventhubs.EventHubProducerClient; +import com.azure.spring.cloud.autoconfigure.implementation.context.AzureGlobalPropertiesAutoConfiguration; +import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.AzureEventHubsAutoConfiguration; +import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsConnectionDetails; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.testcontainers.azure.EventHubsEmulatorContainer; +import org.testcontainers.azure.AzuriteContainer; +import org.testcontainers.containers.Network; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.MountableFile; + +import java.time.Duration; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.waitAtMost; + +@SpringJUnitConfig +@TestPropertySource(properties = { + "spring.cloud.azure.eventhubs.event-hub-name=eh1" +}) +@Testcontainers +@EnabledOnOs(OS.LINUX) +class EventHubsContainerConnectionDetailsFactoryTests { + + private static final Network NETWORK = Network.newNetwork(); + + @Container + private static final AzuriteContainer AZURITE = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:latest") + .withNetwork(NETWORK) + .withNetworkAliases("azurite"); + + @Container + @ServiceConnection + private static final EventHubsEmulatorContainer EVENT_HUBS = new EventHubsEmulatorContainer( + "mcr.microsoft.com/azure-messaging/eventhubs-emulator:latest") + .acceptLicense() + .withCopyFileToContainer(MountableFile.forClasspathResource("eventhubs/Config.json"), + "/Eventhubs_Emulator/ConfigFiles/Config.json") + .withNetwork(NETWORK) + .withAzuriteContainer(AZURITE); + + @Autowired + private AzureEventHubsConnectionDetails connectionDetails; + + @Autowired + private EventHubProducerClient producerClient; + + @Test + void connectionDetailsShouldBeProvidedByFactory() { + assertThat(connectionDetails).isNotNull(); + assertThat(connectionDetails.getConnectionString()) + .isNotBlank() + .startsWith("Endpoint=sb://"); + } + + @Test + void producerClientCanSendMessage() { + // Wait for Event Hubs emulator to be fully ready and event hub entity to be available + waitAtMost(Duration.ofSeconds(120)).pollInterval(Duration.ofSeconds(2)).untilAsserted(() -> { + EventData event = new EventData("Hello World!"); + this.producerClient.send(Collections.singletonList(event)); + }); + } + + @Configuration(proxyBeanMethods = false) + @ImportAutoConfiguration(classes = {AzureGlobalPropertiesAutoConfiguration.class, + AzureEventHubsAutoConfiguration.class}) + static class Config { + } +} diff --git a/sdk/spring/spring-cloud-azure-testcontainers/src/test/resources/eventhubs/Config.json b/sdk/spring/spring-cloud-azure-testcontainers/src/test/resources/eventhubs/Config.json new file mode 100644 index 000000000000..0749990d11d4 --- /dev/null +++ b/sdk/spring/spring-cloud-azure-testcontainers/src/test/resources/eventhubs/Config.json @@ -0,0 +1,20 @@ +{ + "UserConfig": { + "NamespaceConfig": [ + { + "Type": "EventHub", + "Name": "emulatorns1", + "Entities": [ + { + "Name": "eh1", + "PartitionCount": "2", + "ConsumerGroups": [] + } + ] + } + ], + "LoggingConfig": { + "Type": "File" + } + } +}