Skip to content

Commit b09a63b

Browse files
committed
Fix bug: spring.cloud.azure.eventhubs.credential.token-credential-bean-name not take effect in AzureEventHubsMessagingAutoConfiguration
1 parent fbdef9a commit b09a63b

File tree

2 files changed

+89
-6
lines changed

2 files changed

+89
-6
lines changed

sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsMessagingAutoConfiguration.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33

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

6+
import com.azure.core.credential.TokenCredential;
67
import com.azure.messaging.eventhubs.CheckpointStore;
78
import com.azure.messaging.eventhubs.EventData;
89
import com.azure.spring.cloud.autoconfigure.implementation.condition.ConditionalOnAnyProperty;
910
import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsProperties;
11+
import com.azure.spring.cloud.core.implementation.credential.resolver.AzureTokenCredentialResolver;
1012
import com.azure.spring.cloud.core.provider.connectionstring.ServiceConnectionStringProvider;
1113
import com.azure.spring.cloud.core.service.AzureServiceType;
1214
import com.azure.spring.messaging.ConsumerIdentifier;
@@ -27,6 +29,7 @@
2729
import org.slf4j.LoggerFactory;
2830
import org.springframework.beans.BeanUtils;
2931
import org.springframework.beans.factory.ObjectProvider;
32+
import org.springframework.beans.factory.annotation.Qualifier;
3033
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
3134
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
3235
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@@ -37,6 +40,7 @@
3740
import org.springframework.context.annotation.Configuration;
3841
import org.springframework.context.annotation.Import;
3942

43+
import static com.azure.spring.cloud.autoconfigure.implementation.context.AzureContextUtils.DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME;
4044
import static com.azure.spring.cloud.core.implementation.util.AzurePropertiesUtils.copyAzureCommonProperties;
4145

4246
/**
@@ -83,10 +87,16 @@ static class ProcessorContainerConfiguration {
8387
@Bean
8488
@ConditionalOnMissingBean
8589
EventHubsProcessorFactory defaultEventHubsNamespaceProcessorFactory(
86-
NamespaceProperties properties, CheckpointStore checkpointStore,
87-
ObjectProvider<PropertiesSupplier<ConsumerIdentifier, ProcessorProperties>> suppliers) {
88-
return new DefaultEventHubsNamespaceProcessorFactory(checkpointStore, properties,
90+
NamespaceProperties properties,
91+
CheckpointStore checkpointStore,
92+
ObjectProvider<PropertiesSupplier<ConsumerIdentifier, ProcessorProperties>> suppliers,
93+
ObjectProvider<AzureTokenCredentialResolver> tokenCredentialResolvers,
94+
@Qualifier(DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME) ObjectProvider<TokenCredential> defaultTokenCredentials) {
95+
DefaultEventHubsNamespaceProcessorFactory factory = new DefaultEventHubsNamespaceProcessorFactory(checkpointStore, properties,
8996
suppliers.getIfAvailable());
97+
factory.setDefaultCredential(defaultTokenCredentials.getIfAvailable());
98+
factory.setTokenCredentialResolver(tokenCredentialResolvers.getIfAvailable());
99+
return factory;
90100
}
91101

92102
}
@@ -98,8 +108,13 @@ static class EventHubsTemplateConfiguration {
98108
@ConditionalOnMissingBean
99109
EventHubsProducerFactory defaultEventHubsNamespaceProducerFactory(
100110
NamespaceProperties properties,
101-
ObjectProvider<PropertiesSupplier<String, ProducerProperties>> suppliers) {
102-
return new DefaultEventHubsNamespaceProducerFactory(properties, suppliers.getIfAvailable());
111+
ObjectProvider<PropertiesSupplier<String, ProducerProperties>> suppliers,
112+
ObjectProvider<AzureTokenCredentialResolver> tokenCredentialResolvers,
113+
@Qualifier(DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME) ObjectProvider<TokenCredential> defaultTokenCredentials) {
114+
DefaultEventHubsNamespaceProducerFactory factory = new DefaultEventHubsNamespaceProducerFactory(properties, suppliers.getIfAvailable());
115+
factory.setDefaultCredential(defaultTokenCredentials.getIfAvailable());
116+
factory.setTokenCredentialResolver(tokenCredentialResolvers.getIfAvailable());
117+
return factory;
103118
}
104119

105120
@Bean

sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/eventhubs/AzureEventHubsMessagingAutoConfigurationTests.java

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,15 @@
33

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

6+
import com.azure.core.credential.TokenCredential;
67
import com.azure.messaging.eventhubs.CheckpointStore;
8+
import com.azure.spring.cloud.autoconfigure.implementation.context.AzureGlobalPropertiesAutoConfiguration;
9+
import com.azure.spring.cloud.autoconfigure.implementation.context.AzureTokenCredentialAutoConfiguration;
710
import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.configuration.TestCheckpointStore;
11+
import com.azure.spring.cloud.autoconfigure.implementation.eventhubs.properties.AzureEventHubsProperties;
12+
import com.azure.spring.cloud.core.credential.AzureCredentialResolver;
813
import com.azure.spring.messaging.eventhubs.core.EventHubsProcessorFactory;
14+
import com.azure.spring.messaging.eventhubs.core.EventHubsProducerFactory;
915
import com.azure.spring.messaging.eventhubs.core.EventHubsTemplate;
1016
import com.azure.spring.messaging.eventhubs.implementation.support.converter.EventHubsMessageConverter;
1117
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -14,10 +20,15 @@
1420
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
1521
import org.springframework.boot.test.context.FilteredClassLoader;
1622
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
23+
import org.springframework.context.annotation.Bean;
24+
import org.springframework.context.annotation.Configuration;
25+
26+
import java.lang.reflect.Field;
1727

1828
import static com.azure.spring.cloud.autoconfigure.implementation.eventhubs.EventHubsTestUtils.CONNECTION_STRING_FORMAT;
1929
import static org.assertj.core.api.Assertions.assertThat;
2030
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
31+
import static org.mockito.Mockito.mock;
2132

2233
class AzureEventHubsMessagingAutoConfigurationTests {
2334

@@ -121,7 +132,7 @@ void withUserProvidedObjectMapper() {
121132
.withPropertyValues("spring.cloud.azure.eventhubs.connection-string=" + String.format(CONNECTION_STRING_FORMAT, "test-namespace"),
122133
"spring.cloud.azure.message-converter.isolated-object-mapper=false")
123134
.withUserConfiguration(AzureEventHubsPropertiesTestConfiguration.class)
124-
.withBean("userObjectMapper", ObjectMapper.class, () -> new ObjectMapper())
135+
.withBean("userObjectMapper", ObjectMapper.class, ObjectMapper::new)
125136
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class))
126137
.run(context -> {
127138
assertThat(context).hasBean("userObjectMapper");
@@ -130,4 +141,61 @@ void withUserProvidedObjectMapper() {
130141
});
131142
}
132143

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

0 commit comments

Comments
 (0)