Skip to content

Commit fbdef9a

Browse files
committed
Fix bug: Multiple TokenCredential in AzureServiceBusMessagingAutoConfiguration
1 parent dcc772e commit fbdef9a

File tree

2 files changed

+76
-4
lines changed

2 files changed

+76
-4
lines changed

sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusMessagingAutoConfiguration.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.slf4j.LoggerFactory;
3535
import org.springframework.beans.BeanUtils;
3636
import org.springframework.beans.factory.ObjectProvider;
37+
import org.springframework.beans.factory.annotation.Qualifier;
3738
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
3839
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
3940
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@@ -44,6 +45,7 @@
4445
import org.springframework.context.annotation.Configuration;
4546
import org.springframework.context.annotation.Import;
4647

48+
import static com.azure.spring.cloud.autoconfigure.implementation.context.AzureContextUtils.DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME;
4749
import static com.azure.spring.cloud.core.implementation.util.AzurePropertiesUtils.copyAzureCommonProperties;
4850

4951

@@ -92,7 +94,7 @@ ServiceBusProcessorFactory defaultServiceBusNamespaceProcessorFactory(
9294
NamespaceProperties properties,
9395
ObjectProvider<PropertiesSupplier<ConsumerIdentifier, ProcessorProperties>> suppliers,
9496
ObjectProvider<AzureTokenCredentialResolver> tokenCredentialResolvers,
95-
ObjectProvider<TokenCredential> defaultTokenCredentials,
97+
@Qualifier(DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME) ObjectProvider<TokenCredential> defaultTokenCredentials,
9698
ObjectProvider<AzureServiceClientBuilderCustomizer<ServiceBusClientBuilder>> clientBuilderCustomizers,
9799
ObjectProvider<AzureServiceClientBuilderCustomizer<ServiceBusClientBuilder.ServiceBusProcessorClientBuilder>> processorClientBuilderCustomizers,
98100
ObjectProvider<AzureServiceClientBuilderCustomizer<ServiceBusClientBuilder.ServiceBusSessionProcessorClientBuilder>> sessionProcessorClientBuilderCustomizers) {
@@ -115,7 +117,7 @@ ServiceBusConsumerFactory defaultServiceBusNamespaceConsumerFactory(
115117
NamespaceProperties properties,
116118
ObjectProvider<PropertiesSupplier<ConsumerIdentifier, ConsumerProperties>> suppliers,
117119
ObjectProvider<AzureTokenCredentialResolver> tokenCredentialResolvers,
118-
ObjectProvider<TokenCredential> defaultTokenCredentials,
120+
@Qualifier(DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME) ObjectProvider<TokenCredential> defaultTokenCredentials,
119121
ObjectProvider<AzureServiceClientBuilderCustomizer<ServiceBusClientBuilder>> customizers,
120122
ObjectProvider<AzureServiceClientBuilderCustomizer<ServiceBusClientBuilder.ServiceBusSessionReceiverClientBuilder>> sessionReceiverCustomizers) {
121123
DefaultServiceBusNamespaceConsumerFactory factory = new DefaultServiceBusNamespaceConsumerFactory(properties, suppliers.getIfAvailable());
@@ -136,7 +138,7 @@ ServiceBusProducerFactory defaultServiceBusNamespaceProducerFactory(
136138
NamespaceProperties properties,
137139
ObjectProvider<PropertiesSupplier<String, ProducerProperties>> suppliers,
138140
ObjectProvider<AzureTokenCredentialResolver> tokenCredentialResolvers,
139-
ObjectProvider<TokenCredential> defaultTokenCredentials,
141+
@Qualifier(DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME) ObjectProvider<TokenCredential> defaultTokenCredentials,
140142
ObjectProvider<AzureServiceClientBuilderCustomizer<ServiceBusClientBuilder>> clientBuilderCustomizers,
141143
ObjectProvider<AzureServiceClientBuilderCustomizer<ServiceBusClientBuilder.ServiceBusSenderClientBuilder>> senderClientBuilderCustomizers) {
142144
DefaultServiceBusNamespaceProducerFactory factory = new DefaultServiceBusNamespaceProducerFactory(properties, suppliers.getIfAvailable());

sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/servicebus/AzureServiceBusMessagingAutoConfigurationTests.java

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33

44
package com.azure.spring.cloud.autoconfigure.implementation.servicebus;
55

6+
import com.azure.core.credential.TokenCredential;
7+
import com.azure.spring.cloud.autoconfigure.implementation.context.AzureGlobalPropertiesAutoConfiguration;
8+
import com.azure.spring.cloud.autoconfigure.implementation.context.AzureTokenCredentialAutoConfiguration;
9+
import com.azure.spring.cloud.autoconfigure.implementation.servicebus.properties.AzureServiceBusProperties;
10+
import com.azure.spring.cloud.core.credential.AzureCredentialResolver;
611
import com.azure.spring.messaging.servicebus.core.ServiceBusProcessorFactory;
12+
import com.azure.spring.messaging.servicebus.core.ServiceBusProducerFactory;
713
import com.azure.spring.messaging.servicebus.core.ServiceBusTemplate;
814
import com.azure.spring.messaging.servicebus.implementation.support.converter.ServiceBusMessageConverter;
915
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -12,10 +18,15 @@
1218
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
1319
import org.springframework.boot.test.context.FilteredClassLoader;
1420
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
21+
import org.springframework.context.annotation.Bean;
22+
import org.springframework.context.annotation.Configuration;
23+
24+
import java.lang.reflect.Field;
1525

1626
import static com.azure.spring.cloud.autoconfigure.implementation.util.TestServiceBusUtils.CONNECTION_STRING_FORMAT;
1727
import static org.assertj.core.api.Assertions.assertThat;
1828
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
29+
import static org.mockito.Mockito.mock;
1930

2031
class AzureServiceBusMessagingAutoConfigurationTests {
2132

@@ -117,7 +128,7 @@ void withUserProvidedObjectMapper() {
117128
.withPropertyValues("spring.cloud.azure.servicebus.connection-string=" + String.format(CONNECTION_STRING_FORMAT, "test-namespace"),
118129
"spring.cloud.azure.message-converter.isolated-object-mapper=false")
119130
.withUserConfiguration(AzureServiceBusPropertiesTestConfiguration.class)
120-
.withBean("userObjectMapper", ObjectMapper.class, () -> new ObjectMapper())
131+
.withBean("userObjectMapper", ObjectMapper.class, ObjectMapper::new)
121132
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class))
122133
.run(context -> {
123134
assertThat(context).hasBean("userObjectMapper");
@@ -126,4 +137,63 @@ void withUserProvidedObjectMapper() {
126137
});
127138
}
128139

140+
@Test
141+
void testCustomTokenCredentialConfiguration() {
142+
this.contextRunner
143+
.withConfiguration(AutoConfigurations.of(CustomTokenCredentialConfiguration.class,
144+
AzureTokenCredentialAutoConfiguration.class,
145+
AzureGlobalPropertiesAutoConfiguration.class))
146+
.withBean(ServiceBusMessageConverter.class, () -> mock(ServiceBusMessageConverter.class))
147+
.withPropertyValues(
148+
"spring.cloud.azure.servicebus.connection-string=" + String.format(CONNECTION_STRING_FORMAT, "test-namespace"),
149+
"spring.cloud.azure.servicebus.credential.token-credential-bean-name=customTokenCredential"
150+
)
151+
.withUserConfiguration(AzureServiceBusPropertiesTestConfiguration.class)
152+
.run(context -> {
153+
154+
// Verify that the properties contain the correct credential bean name
155+
AzureServiceBusProperties serviceBusProperties = context.getBean(AzureServiceBusProperties.class);
156+
assertThat(serviceBusProperties).isNotNull();
157+
assertThat(serviceBusProperties.getCredential()).isNotNull();
158+
assertThat(serviceBusProperties.getCredential().getTokenCredentialBeanName())
159+
.as("The token-credential-bean-name property should be set to customTokenCredential")
160+
.isEqualTo("customTokenCredential");
161+
162+
// Verify that the custom token credential bean exists
163+
assertThat(context).hasBean("customTokenCredential");
164+
TokenCredential customCredential = context.getBean("customTokenCredential", TokenCredential.class);
165+
assertThat(customCredential).isNotNull();
166+
167+
// Verify the ServiceBusProducerFactory has the tokenCredentialResolver configured
168+
assertThat(context).hasSingleBean(ServiceBusProducerFactory.class);
169+
ServiceBusProducerFactory producerFactory = context.getBean(ServiceBusProducerFactory.class);
170+
assertThat(producerFactory).isNotNull();
171+
172+
// Verify tokenCredentialResolver resolves to the custom credential
173+
Field tokenCredentialResolverField =
174+
producerFactory.getClass().getDeclaredField("tokenCredentialResolver");
175+
tokenCredentialResolverField.setAccessible(true);
176+
Object tokenCredentialResolver = tokenCredentialResolverField.get(producerFactory);
177+
assertThat(tokenCredentialResolver)
178+
.as("TokenCredentialResolver should be configured").isNotNull();
179+
180+
// Cast to AzureCredentialResolver and invoke resolve() to verify it returns customTokenCredential
181+
@SuppressWarnings("unchecked")
182+
AzureCredentialResolver<TokenCredential> resolver =
183+
(AzureCredentialResolver<TokenCredential>) tokenCredentialResolver;
184+
TokenCredential resolvedCredential = resolver.resolve(serviceBusProperties);
185+
assertThat(resolvedCredential)
186+
.as("The resolved credential should be the customTokenCredential bean")
187+
.isSameAs(customCredential);
188+
});
189+
}
190+
191+
@Configuration
192+
public static class CustomTokenCredentialConfiguration {
193+
@Bean
194+
public TokenCredential customTokenCredential() {
195+
return mock(TokenCredential.class);
196+
}
197+
}
198+
129199
}

0 commit comments

Comments
 (0)