diff --git a/sdk/spring/CHANGELOG.md b/sdk/spring/CHANGELOG.md index c79ef3e9d2325..31e37ba1513c9 100644 --- a/sdk/spring/CHANGELOG.md +++ b/sdk/spring/CHANGELOG.md @@ -12,6 +12,7 @@ This section includes changes in `spring-cloud-azure-autoconfigure` module. #### Bugs Fixed - Fix error: Event Hubs connection string is still used when it's configured to empty string. [#42880](https://github.com/Azure/azure-sdk-for-java/issues/42880). - Fix error: Service Bus connection string is still used when it's configured to empty string. [#42880](https://github.com/Azure/azure-sdk-for-java/issues/42880). +- Fix warn logs: Mark the bean post processor related beans as internal to avoid the log 'Bean xxx of type xxx is not eligible for getting processed by all BeanPostProcessors'. [#38631](https://github.com/Azure/azure-sdk-for-java/issues/38631). ### Spring Integration Azure Core This section includes changes in the `spring-integration-azure-core` module. diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureServiceClientBuilderFactoryConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureServiceClientBuilderFactoryConfiguration.java new file mode 100644 index 0000000000000..599d3f6c1e6ad --- /dev/null +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureServiceClientBuilderFactoryConfiguration.java @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.autoconfigure.implementation.context; + +import com.azure.spring.cloud.core.implementation.factory.AbstractAzureServiceClientBuilderFactory; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Role; + +/** + * {@code @Configuration} class that registers a {@link AzureServiceClientBuilderFactoryPostProcessor} + * bean capable of processing the {@link AbstractAzureServiceClientBuilderFactory } bean. + * + * @since 5.19.0 + */ +@Configuration(proxyBeanMethods = false) +@Role(BeanDefinition.ROLE_INFRASTRUCTURE) +class AzureServiceClientBuilderFactoryConfiguration { + + /** + * The BeanPostProcessor to apply the default token credential and resolver to all service client builder factories. + * @return the BPP. + */ + @Bean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + static AzureServiceClientBuilderFactoryPostProcessor builderFactoryBeanPostProcessor() { + return new AzureServiceClientBuilderFactoryPostProcessor(); + } +} diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureServiceClientBuilderFactoryPostProcessor.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureServiceClientBuilderFactoryPostProcessor.java new file mode 100644 index 0000000000000..37e8e08ab77e5 --- /dev/null +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureServiceClientBuilderFactoryPostProcessor.java @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.autoconfigure.implementation.context; + +import com.azure.core.credential.TokenCredential; +import com.azure.spring.cloud.core.implementation.credential.resolver.AzureTokenCredentialResolver; +import com.azure.spring.cloud.core.implementation.factory.AbstractAzureServiceClientBuilderFactory; +import com.azure.spring.cloud.core.implementation.factory.credential.AbstractAzureCredentialBuilderFactory; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.config.BeanPostProcessor; + +import static com.azure.spring.cloud.autoconfigure.implementation.context.AzureContextUtils.DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME; + +/** + * {@link BeanPostProcessor} for {@link AbstractAzureServiceClientBuilderFactory} to configure default credential and resolver. + */ +class AzureServiceClientBuilderFactoryPostProcessor implements BeanPostProcessor, BeanFactoryAware { + + private BeanFactory beanFactory; + + @Override + @SuppressWarnings({ "rawtypes", "unchecked" }) + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (bean instanceof AbstractAzureCredentialBuilderFactory) { + return bean; + } + + if (bean instanceof AbstractAzureServiceClientBuilderFactory + && beanFactory.containsBean(DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME)) { + AbstractAzureServiceClientBuilderFactory factory = (AbstractAzureServiceClientBuilderFactory) bean; + factory.setDefaultTokenCredential( + (TokenCredential) beanFactory.getBean(DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME)); + factory.setTokenCredentialResolver(beanFactory.getBean(AzureTokenCredentialResolver.class)); + } + return bean; + } + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = beanFactory; + } +} diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureTokenCredentialAutoConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureTokenCredentialAutoConfiguration.java index 71db28c690f7a..8d672810f2aab 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureTokenCredentialAutoConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureTokenCredentialAutoConfiguration.java @@ -14,8 +14,6 @@ import com.azure.spring.cloud.autoconfigure.implementation.properties.core.AbstractAzureHttpConfigurationProperties; import com.azure.spring.cloud.core.customizer.AzureServiceClientBuilderCustomizer; import com.azure.spring.cloud.core.implementation.credential.resolver.AzureTokenCredentialResolver; -import com.azure.spring.cloud.core.implementation.factory.AbstractAzureServiceClientBuilderFactory; -import com.azure.spring.cloud.core.implementation.factory.credential.AbstractAzureCredentialBuilderFactory; import com.azure.spring.cloud.core.implementation.factory.credential.ClientCertificateCredentialBuilderFactory; import com.azure.spring.cloud.core.implementation.factory.credential.ClientSecretCredentialBuilderFactory; import com.azure.spring.cloud.core.implementation.factory.credential.DefaultAzureCredentialBuilderFactory; @@ -24,18 +22,15 @@ import com.azure.spring.cloud.core.provider.authentication.TokenCredentialOptionsProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.annotation.Order; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @@ -52,6 +47,7 @@ */ @Configuration(proxyBeanMethods = false) @AutoConfigureAfter(TaskExecutionAutoConfiguration.class) +@Import(AzureServiceClientBuilderFactoryConfiguration.class) public class AzureTokenCredentialAutoConfiguration extends AzureServiceConfigurationBase { private static final Logger LOGGER = LoggerFactory.getLogger(AzureTokenCredentialAutoConfiguration.class); @@ -212,15 +208,6 @@ UsernamePasswordCredentialBuilderFactory usernamePasswordCredentialBuilderFactor return factory; } - /** - * The BeanPostProcessor to apply the default token credential to all service client builder factories. - * @return the BPP. - */ - @Bean - static AzureServiceClientBuilderFactoryPostProcessor builderFactoryBeanPostProcessor() { - return new AzureServiceClientBuilderFactoryPostProcessor(); - } - @Bean(name = DEFAULT_CREDENTIAL_TASK_EXECUTOR_BEAN_NAME) @ConditionalOnMissingBean(name = DEFAULT_CREDENTIAL_TASK_EXECUTOR_BEAN_NAME) ThreadPoolTaskExecutor credentialTaskExecutor() { @@ -231,33 +218,6 @@ ThreadPoolTaskExecutor credentialTaskExecutor() { return executor; } - static class AzureServiceClientBuilderFactoryPostProcessor implements BeanPostProcessor, BeanFactoryAware { - - private BeanFactory beanFactory; - - @Override - @SuppressWarnings({ "rawtypes", "unchecked" }) - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof AbstractAzureCredentialBuilderFactory) { - return bean; - } - - if (bean instanceof AbstractAzureServiceClientBuilderFactory - && beanFactory.containsBean(DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME)) { - AbstractAzureServiceClientBuilderFactory factory = (AbstractAzureServiceClientBuilderFactory) bean; - factory.setDefaultTokenCredential( - (TokenCredential) beanFactory.getBean(DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME)); - factory.setTokenCredentialResolver(beanFactory.getBean(AzureTokenCredentialResolver.class)); - } - return bean; - } - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = beanFactory; - } - } - static class IdentityClientProperties extends AbstractAzureHttpConfigurationProperties { } 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 1c24f06cca77e..b2bbf55eacfa6 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 @@ -14,13 +14,13 @@ import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 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.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.core.env.Environment; import org.springframework.kafka.core.KafkaTemplate; @@ -36,6 +36,7 @@ @ConditionalOnClass(KafkaTemplate.class) @ConditionalOnProperty(value = "spring.cloud.azure.eventhubs.kafka.enabled", havingValue = "true", matchIfMissing = true) @AutoConfigureAfter({ AzureEventHubsAutoConfiguration.class, AzureEventHubsResourceManagerAutoConfiguration.class }) +@Import(KafkaPropertiesConfiguration.class) public class AzureEventHubsKafkaAutoConfiguration { private static final Logger LOGGER = LoggerFactory.getLogger(AzureEventHubsKafkaAutoConfiguration.class); @@ -55,12 +56,4 @@ StaticConnectionStringProvider eventHubsKafkaConnect return new StaticConnectionStringProvider<>(AzureServiceType.EVENT_HUBS, connectionString); } - - @Bean - @ConditionalOnBean(value = AzureServiceType.EventHubs.class, parameterizedContainer = ServiceConnectionStringProvider.class) - static KafkaPropertiesBeanPostProcessor kafkaPropertiesBeanPostProcessor( - ServiceConnectionStringProvider connectionStringProvider) { - return new KafkaPropertiesBeanPostProcessor(connectionStringProvider); - } - } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/kafka/KafkaPropertiesConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/kafka/KafkaPropertiesConfiguration.java new file mode 100644 index 0000000000000..e8c882df3b70b --- /dev/null +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/kafka/KafkaPropertiesConfiguration.java @@ -0,0 +1,35 @@ +// 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.kafka.AzureEventHubsKafkaOAuth2AutoConfiguration; +import com.azure.spring.cloud.core.provider.connectionstring.ServiceConnectionStringProvider; +import com.azure.spring.cloud.core.service.AzureServiceType; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.kafka.KafkaProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Role; + +/** + * {@code @Configuration} class that registers a {@link KafkaPropertiesBeanPostProcessor} + * bean capable of processing Kafka properties @{@link KafkaProperties}. + * + * @since 5.19.0 + * @deprecated 4.3.0 in favor of {@link AzureEventHubsKafkaOAuth2AutoConfiguration}. + */ +@Deprecated +@Configuration(proxyBeanMethods = false) +@Role(BeanDefinition.ROLE_INFRASTRUCTURE) +class KafkaPropertiesConfiguration { + + @Bean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + @ConditionalOnBean(value = AzureServiceType.EventHubs.class, parameterizedContainer = ServiceConnectionStringProvider.class) + static KafkaPropertiesBeanPostProcessor kafkaPropertiesBeanPostProcessor( + ServiceConnectionStringProvider connectionStringProvider) { + return new KafkaPropertiesBeanPostProcessor(connectionStringProvider); + } +} diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jdbc/AzureJdbcAutoConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jdbc/AzureJdbcAutoConfiguration.java index 9cb55b4266ea4..38a987fc74f06 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jdbc/AzureJdbcAutoConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jdbc/AzureJdbcAutoConfiguration.java @@ -3,6 +3,7 @@ package com.azure.spring.cloud.autoconfigure.implementation.jdbc; import com.azure.identity.extensions.implementation.template.AzureAuthenticationTemplate; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -12,6 +13,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Role; /** @@ -21,6 +23,7 @@ * @since 4.5.0 */ @Configuration(proxyBeanMethods = false) +@Role(BeanDefinition.ROLE_INFRASTRUCTURE) @ConditionalOnBean(DataSourceProperties.class) @ConditionalOnClass(AzureAuthenticationTemplate.class) @AutoConfigureAfter(DataSourceAutoConfiguration.class) @@ -28,7 +31,8 @@ public class AzureJdbcAutoConfiguration { @Bean @ConditionalOnMissingBean - JdbcPropertiesBeanPostProcessor jdbcConfigurationPropertiesBeanPostProcessor() { + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + static JdbcPropertiesBeanPostProcessor jdbcConfigurationPropertiesBeanPostProcessor() { return new JdbcPropertiesBeanPostProcessor(); } } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsAutoConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsAutoConfiguration.java index cf0afa76abf5a..9f8fe941a297b 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsAutoConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsAutoConfiguration.java @@ -4,15 +4,12 @@ package com.azure.spring.cloud.autoconfigure.implementation.jms; import com.azure.servicebus.jms.ServiceBusJmsConnectionFactory; -import com.azure.spring.cloud.autoconfigure.implementation.condition.ConditionalOnMissingProperty; import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties; import com.azure.spring.cloud.autoconfigure.implementation.jms.properties.AzureServiceBusJmsProperties; import com.azure.spring.cloud.autoconfigure.implementation.resourcemanager.AzureServiceBusResourceManagerAutoConfiguration; import com.azure.spring.cloud.autoconfigure.jms.AzureServiceBusJmsConnectionFactoryCustomizer; import com.azure.spring.cloud.core.implementation.util.AzurePasswordlessPropertiesUtils; import com.azure.spring.cloud.core.implementation.util.ReflectionUtils; -import com.azure.spring.cloud.core.provider.connectionstring.ServiceConnectionStringProvider; -import com.azure.spring.cloud.core.service.AzureServiceType; import jakarta.jms.Connection; import jakarta.jms.ConnectionFactory; import org.apache.qpid.jms.JmsConnectionExtensions; @@ -23,7 +20,6 @@ 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.autoconfigure.jms.JmsAutoConfiguration; import org.springframework.boot.autoconfigure.jms.JmsProperties; @@ -52,7 +48,10 @@ @ConditionalOnProperty(value = "spring.jms.servicebus.enabled", matchIfMissing = true) @ConditionalOnClass({ ConnectionFactory.class, JmsConnectionFactory.class, JmsTemplate.class }) @EnableConfigurationProperties({ JmsProperties.class }) -@Import({ ServiceBusJmsConnectionFactoryConfiguration.class, ServiceBusJmsContainerConfiguration.class }) +@Import({ + ServiceBusJmsConnectionFactoryConfiguration.class, + ServiceBusJmsContainerConfiguration.class, + ServiceBusJmsPropertiesConfiguration.class }) public class ServiceBusJmsAutoConfiguration { @Bean @@ -86,14 +85,6 @@ AzureServiceBusJmsConnectionFactoryCustomizer amqpOpenPropertiesCustomizer(Objec }; } - @Bean - @ConditionalOnMissingBean - @ConditionalOnMissingProperty(prefix = "spring.jms.servicebus", name = "connection-string") - static AzureServiceBusJmsPropertiesBeanPostProcessor azureServiceBusJmsPropertiesBeanPostProcessor( - ObjectProvider> connectionStringProviders) { - return new AzureServiceBusJmsPropertiesBeanPostProcessor(connectionStringProviders); - } - private AzureServiceBusJmsProperties mergeAzureProperties(AzureGlobalProperties azureGlobalProperties, AzureServiceBusJmsProperties azurePasswordlessProperties) { AzureServiceBusJmsProperties mergedProperties = new AzureServiceBusJmsProperties(); AzurePasswordlessPropertiesUtils.mergeAzureCommonProperties(azureGlobalProperties, azurePasswordlessProperties, mergedProperties); diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsPropertiesConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsPropertiesConfiguration.java new file mode 100644 index 0000000000000..9097b83924b22 --- /dev/null +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/jms/ServiceBusJmsPropertiesConfiguration.java @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.autoconfigure.implementation.jms; + +import com.azure.spring.cloud.autoconfigure.implementation.condition.ConditionalOnMissingProperty; +import com.azure.spring.cloud.autoconfigure.implementation.jms.properties.AzureServiceBusJmsProperties; +import com.azure.spring.cloud.core.provider.connectionstring.ServiceConnectionStringProvider; +import com.azure.spring.cloud.core.service.AzureServiceType; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Role; + +/** + * {@code @Configuration} class that registers a {@link AzureServiceBusJmsPropertiesBeanPostProcessor} + * bean capable of processing Service Bus JMS properties @{@link AzureServiceBusJmsProperties}. + * + * @since 5.19.0 + */ +@Configuration(proxyBeanMethods = false) +@Role(BeanDefinition.ROLE_INFRASTRUCTURE) +class ServiceBusJmsPropertiesConfiguration { + + @Bean + @ConditionalOnMissingBean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + @ConditionalOnMissingProperty(prefix = "spring.jms.servicebus", name = "connection-string") + static AzureServiceBusJmsPropertiesBeanPostProcessor azureServiceBusJmsPropertiesBeanPostProcessor( + ObjectProvider> connectionStringProviders) { + return new AzureServiceBusJmsPropertiesBeanPostProcessor(connectionStringProviders); + } +} diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/kafka/AzureEventHubsKafkaBinderOAuth2AutoConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/kafka/AzureEventHubsKafkaBinderOAuth2AutoConfiguration.java index 49da57ed13235..316017a9d715f 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/kafka/AzureEventHubsKafkaBinderOAuth2AutoConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/kafka/AzureEventHubsKafkaBinderOAuth2AutoConfiguration.java @@ -8,6 +8,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.stream.binder.kafka.config.KafkaBinderConfiguration; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; /** * {@link EnableAutoConfiguration Auto-configuration} for Azure Event Hubs Kafka Azure Identity support on Spring Cloud Stream framework. @@ -17,6 +18,7 @@ * * @since 4.4.0 */ +@Configuration(proxyBeanMethods = false) @ConditionalOnClass(KafkaBinderConfiguration.class) @ConditionalOnProperty(value = "spring.cloud.azure.eventhubs.kafka.enabled", havingValue = "true", matchIfMissing = true) public class AzureEventHubsKafkaBinderOAuth2AutoConfiguration { diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/kafka/AzureEventHubsKafkaOAuth2AutoConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/kafka/AzureEventHubsKafkaOAuth2AutoConfiguration.java index fce8f65dc1249..aa5a62787c0e0 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/kafka/AzureEventHubsKafkaOAuth2AutoConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/kafka/AzureEventHubsKafkaOAuth2AutoConfiguration.java @@ -3,12 +3,14 @@ package com.azure.spring.cloud.autoconfigure.implementation.kafka; import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Role; import org.springframework.kafka.core.KafkaTemplate; import static com.azure.spring.cloud.autoconfigure.implementation.context.AzureContextUtils.PASSWORDLESS_KAFKA_PROPERTIES_BEAN_POST_PROCESSOR_BEAN_NAME; @@ -20,11 +22,13 @@ * @since 4.3.0 */ @Configuration(proxyBeanMethods = false) +@Role(BeanDefinition.ROLE_INFRASTRUCTURE) @ConditionalOnClass(KafkaTemplate.class) @ConditionalOnProperty(value = "spring.cloud.azure.eventhubs.kafka.enabled", havingValue = "true", matchIfMissing = true) public class AzureEventHubsKafkaOAuth2AutoConfiguration { @Bean(PASSWORDLESS_KAFKA_PROPERTIES_BEAN_POST_PROCESSOR_BEAN_NAME) + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) static BeanPostProcessor kafkaPropertiesBeanPostProcessor(AzureGlobalProperties properties) { return new KafkaPropertiesBeanPostProcessor(properties); } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/kafka/AzureKafkaSpringCloudStreamConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/kafka/AzureKafkaSpringCloudStreamConfiguration.java index 531a51f751f03..44d9b60d10168 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/kafka/AzureKafkaSpringCloudStreamConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/kafka/AzureKafkaSpringCloudStreamConfiguration.java @@ -4,11 +4,13 @@ import com.azure.spring.cloud.autoconfigure.implementation.context.AzureGlobalPropertiesAutoConfiguration; import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.cloud.stream.binder.kafka.KafkaMessageChannelBinder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.Role; /** * Configuration for OAuth2 support on Spring Cloud Stream Kafka Binder. Provide Azure Identity-based @@ -16,12 +18,14 @@ * * @since 4.3.0 */ -@ConditionalOnClass(KafkaMessageChannelBinder.class) @Configuration(proxyBeanMethods = false) +@Role(BeanDefinition.ROLE_INFRASTRUCTURE) +@ConditionalOnClass(KafkaMessageChannelBinder.class) @Import(AzureGlobalPropertiesAutoConfiguration.class) public class AzureKafkaSpringCloudStreamConfiguration { @Bean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) static KafkaBinderConfigurationPropertiesBeanPostProcessor kafkaBinderConfigurationPropertiesBeanPostProcessor( AzureGlobalProperties azureGlobalProperties) { return new KafkaBinderConfigurationPropertiesBeanPostProcessor(azureGlobalProperties); diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureServiceClientBuilderFactoryConfigurationTests.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureServiceClientBuilderFactoryConfigurationTests.java new file mode 100644 index 0000000000000..b3583be25ffd1 --- /dev/null +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureServiceClientBuilderFactoryConfigurationTests.java @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.autoconfigure.implementation.context; + +import com.azure.core.credential.TokenCredential; +import com.azure.identity.DefaultAzureCredential; +import com.azure.spring.cloud.autoconfigure.implementation.context.properties.AzureGlobalProperties; +import com.azure.spring.cloud.autoconfigure.implementation.cosmos.properties.AzureCosmosProperties; +import com.azure.spring.cloud.core.implementation.credential.resolver.AzureTokenCredentialResolver; +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; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class AzureServiceClientBuilderFactoryConfigurationTests { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(AzureTokenCredentialAutoConfiguration.class)); + + @Test + void defaultAzureCredentialSetToBuilderFactories() { + TestCosmosClientBuilderFactory builderFactory = new TestCosmosClientBuilderFactory(new AzureCosmosProperties()); + contextRunner + .withBean(AzureGlobalProperties.class, AzureGlobalProperties::new) + .withBean(TestCosmosClientBuilderFactory.class, () -> builderFactory) + .run(context -> { + assertThat(context).hasSingleBean(AzureServiceClientBuilderFactoryPostProcessor.class); + assertThat(context).hasSingleBean(TokenCredential.class); + + TokenCredential tokenCredential = context.getBean(TokenCredential.class); + assertTrue(tokenCredential instanceof DefaultAzureCredential); + assertEquals(builderFactory.getDefaultTokenCredential(), tokenCredential); + }); + } + + @Test + void defaultAzureCredentialResolverSetToBuilderFactories() { + TestCosmosClientBuilderFactory builderFactory = new TestCosmosClientBuilderFactory(new AzureCosmosProperties()); + contextRunner + .withBean(AzureGlobalProperties.class, AzureGlobalProperties::new) + .withBean(TestCosmosClientBuilderFactory.class, () -> builderFactory) + .run(context -> { + assertThat(context).hasSingleBean(AzureServiceClientBuilderFactoryPostProcessor.class); + assertThat(context).hasSingleBean(AzureTokenCredentialResolver.class); + + AzureTokenCredentialResolver tokenCredentialResolver = context.getBean(AzureTokenCredentialResolver.class); + assertEquals(builderFactory.getAzureTokenCredentialResolver(), tokenCredentialResolver); + }); + } +} diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureTokenCredentialAutoConfigurationTests.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureTokenCredentialAutoConfigurationTests.java index e3d28e98d2bc5..6b1ae3c7a3ad8 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureTokenCredentialAutoConfigurationTests.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/context/AzureTokenCredentialAutoConfigurationTests.java @@ -14,16 +14,12 @@ 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.cosmos.properties.AzureCosmosProperties; -import com.azure.spring.cloud.core.credential.AzureCredentialResolver; import com.azure.spring.cloud.core.implementation.credential.resolver.AzureTokenCredentialResolver; import com.azure.spring.cloud.core.implementation.factory.credential.ClientCertificateCredentialBuilderFactory; import com.azure.spring.cloud.core.implementation.factory.credential.ClientSecretCredentialBuilderFactory; import com.azure.spring.cloud.core.implementation.factory.credential.DefaultAzureCredentialBuilderFactory; import com.azure.spring.cloud.core.implementation.factory.credential.ManagedIdentityCredentialBuilderFactory; import com.azure.spring.cloud.core.implementation.factory.credential.UsernamePasswordCredentialBuilderFactory; -import com.azure.spring.cloud.service.implementation.cosmos.CosmosClientBuilderFactory; -import com.azure.spring.cloud.service.implementation.cosmos.CosmosClientProperties; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -267,37 +263,6 @@ void defaultCredentialThreadPoolShouldNotConfigureWhenOverride() { }); } - @Test - void defaultAzureCredentialSetToBuilderFactories() { - CosmosClientBuilderFactoryExt builderFactory = new CosmosClientBuilderFactoryExt(new AzureCosmosProperties()); - contextRunner - .withBean(AzureGlobalProperties.class, AzureGlobalProperties::new) - .withBean(CosmosClientBuilderFactoryExt.class, () -> builderFactory) - .run(context -> { - assertThat(context).hasSingleBean(AzureTokenCredentialAutoConfiguration.AzureServiceClientBuilderFactoryPostProcessor.class); - assertThat(context).hasSingleBean(TokenCredential.class); - - TokenCredential tokenCredential = context.getBean(TokenCredential.class); - assertTrue(tokenCredential instanceof DefaultAzureCredential); - assertEquals(builderFactory.getDefaultTokenCredential(), tokenCredential); - }); - } - - @Test - void defaultAzureCredentialResolverSetToBuilderFactories() { - CosmosClientBuilderFactoryExt builderFactory = new CosmosClientBuilderFactoryExt(new AzureCosmosProperties()); - contextRunner - .withBean(AzureGlobalProperties.class, AzureGlobalProperties::new) - .withBean(CosmosClientBuilderFactoryExt.class, () -> builderFactory) - .run(context -> { - assertThat(context).hasSingleBean(AzureTokenCredentialAutoConfiguration.AzureServiceClientBuilderFactoryPostProcessor.class); - assertThat(context).hasSingleBean(AzureTokenCredentialResolver.class); - - AzureTokenCredentialResolver tokenCredentialResolver = context.getBean(AzureTokenCredentialResolver.class); - assertEquals(builderFactory.getAzureTokenCredentialResolver(), tokenCredentialResolver); - }); - } - @Test void globalPropertiesShouldBeHonored() { AzureGlobalProperties properties = new AzureGlobalProperties(); @@ -367,32 +332,4 @@ private static class OtherBuilderCustomizer extends TestBuilderCustomizer azureTokenCredentialResolver; - - CosmosClientBuilderFactoryExt(CosmosClientProperties cosmosClientProperties) { - super(cosmosClientProperties); - } - - @Override - public void setDefaultTokenCredential(TokenCredential defaultTokenCredential) { - this.defaultTokenCredential = defaultTokenCredential; - } - - @Override - public void setTokenCredentialResolver(AzureCredentialResolver tokenCredentialResolver) { - this.azureTokenCredentialResolver = tokenCredentialResolver; - } - - TokenCredential getDefaultTokenCredential() { - return defaultTokenCredential; - } - - AzureCredentialResolver getAzureTokenCredentialResolver() { - return azureTokenCredentialResolver; - } - } - } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/context/TestCosmosClientBuilderFactory.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/context/TestCosmosClientBuilderFactory.java new file mode 100644 index 0000000000000..b08c981488222 --- /dev/null +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/context/TestCosmosClientBuilderFactory.java @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.spring.cloud.autoconfigure.implementation.context; + +import com.azure.core.credential.TokenCredential; +import com.azure.spring.cloud.core.credential.AzureCredentialResolver; +import com.azure.spring.cloud.service.implementation.cosmos.CosmosClientBuilderFactory; +import com.azure.spring.cloud.service.implementation.cosmos.CosmosClientProperties; + +class TestCosmosClientBuilderFactory extends CosmosClientBuilderFactory { + + private TokenCredential defaultTokenCredential; + private AzureCredentialResolver azureTokenCredentialResolver; + + TestCosmosClientBuilderFactory(CosmosClientProperties cosmosClientProperties) { + super(cosmosClientProperties); + } + + @Override + public void setDefaultTokenCredential(TokenCredential defaultTokenCredential) { + this.defaultTokenCredential = defaultTokenCredential; + } + + @Override + public void setTokenCredentialResolver(AzureCredentialResolver tokenCredentialResolver) { + this.azureTokenCredentialResolver = tokenCredentialResolver; + } + + TokenCredential getDefaultTokenCredential() { + return defaultTokenCredential; + } + + AzureCredentialResolver getAzureTokenCredentialResolver() { + return azureTokenCredentialResolver; + } +} 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 index 8eb24d6d593ee..ce5c41189e19d 100644 --- 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 @@ -34,7 +34,8 @@ class AzureEventHubsKafkaAutoConfigurationTests { "Endpoint=sb://%s.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=key"; private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(AzureEventHubsKafkaAutoConfiguration.class, KafkaAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(AzureEventHubsKafkaAutoConfiguration.class, + KafkaPropertiesConfiguration.class, KafkaAutoConfiguration.class)); @Test void shouldNotConfigureWhenAzureEventHubsKafkaDisabled() { this.contextRunner diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/kafka/AzureEventHubsKafkaConfigurationTests.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/kafka/AzureEventHubsKafkaConfigurationTests.java index 49cb97b413044..c5d5365461f01 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/kafka/AzureEventHubsKafkaConfigurationTests.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/kafka/AzureEventHubsKafkaConfigurationTests.java @@ -36,7 +36,7 @@ class AzureEventHubsKafkaConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withConfiguration(AutoConfigurations.of(AzureEventHubsKafkaOAuth2AutoConfiguration.class, AzureEventHubsKafkaAutoConfiguration.class, AzureGlobalPropertiesAutoConfiguration.class, TestSpringTokenCredentialProviderContextProviderAutoConfiguration.class, - AzureTokenCredentialAutoConfiguration.class, + AzureTokenCredentialAutoConfiguration.class, KafkaPropertiesConfiguration.class, KafkaAutoConfiguration.class, AzureKafkaSpringCloudStreamConfiguration.class, KafkaBinderConfiguration.class));