azure-sdk-for-java
azure-sdk-for-java copied to clipboard
[BUG] Spring presents Bean selection issues when passwordless and resource-manager are used together.
Maven:
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-dependencies</artifactId>
<version>4.15.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-jdbc-mysql</artifactId>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter</artifactId>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-resourcemanager</artifactId>
</dependency>
Properties:
# Database
spring.datasource.azure.passwordless-enabled=true
# ResourceManager
spring.cloud.azure.resource-manager.enabled=true
When I started springboot, I got the following error:
Parameter 0 of method azureResourceManager in com.azure.spring.cloud.autoconfigure.resourcemanager.AzureResourceManagerAutoConfiguration required a single bean, but 2 were found:
- springCloudAzureDefaultCredential: defined by method 'tokenCredential' in class path resource [com/azure/spring/cloud/autoconfigure/context/AzureTokenCredentialAutoConfiguration.class]
- passwordlessTokenCredential: defined in unknown location
I found in JdbcPropertiesBeanPostProcessor.class registered here TokenCredential.class.
private Map<String, String> buildEnhancedProperties(DatabaseType databaseType, AzureJdbcPasswordlessProperties properties) {
Map<String, String> result = new HashMap<>();
TokenCredentialProvider tokenCredentialProvider = TokenCredentialProvider.createDefault(new TokenCredentialProviderOptions(properties.toPasswordlessProperties()));
TokenCredential tokenCredential = tokenCredentialProvider.get();
AuthProperty.TOKEN_CREDENTIAL_BEAN_NAME.setProperty(result, PASSWORDLESS_TOKEN_CREDENTIAL_BEAN_NAME);
applicationContext.registerBean(PASSWORDLESS_TOKEN_CREDENTIAL_BEAN_NAME, TokenCredential.class, () -> tokenCredential);
LOGGER.debug("Add SpringTokenCredentialProvider as the default token credential provider.");
AuthProperty.TOKEN_CREDENTIAL_PROVIDER_CLASS_NAME.setProperty(result, SPRING_TOKEN_CREDENTIAL_PROVIDER_CLASS_NAME);
AuthProperty.AUTHORITY_HOST.setProperty(result, properties.getProfile().getEnvironment().getActiveDirectoryEndpoint());
databaseType.setDefaultEnhancedProperties(result);
return result;
}
At the same time also registered a TokenCredential.class AzureTokenCredentialAutoConfiguration.class here.
@ConditionalOnMissingBean(name = DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME)
@Bean(name = DEFAULT_TOKEN_CREDENTIAL_BEAN_NAME)
@Order
TokenCredential tokenCredential(DefaultAzureCredentialBuilderFactory factory,
AzureTokenCredentialResolver resolver) {
TokenCredential globalTokenCredential = resolver.resolve(this.identityClientProperties);
if (globalTokenCredential != null) {
return globalTokenCredential;
} else {
return factory.build().build();
}
}
So when AzureResourceManagerAutoConfiguration.class use TokenCredential.class, there is a mistake.
@Bean
@ConditionalOnMissingBean
public AzureResourceManager azureResourceManager(TokenCredential tokenCredential, AzureProfile azureProfile) {
// TODO (xiada) Do we need to pass our User-Agent to with the management sdk?
// TODO (xiada) configure the http client of arm client
return AzureResourceManager.configure().authenticate(tokenCredential, azureProfile).withDefaultSubscription();
}
Does anyone know how to fix this? Thank you very much for your answer.
@saragluna could you please follow up with @DebugXie
Hi @DebugXie , Thank you for reporting this issue. We have received your submission and will take a look. We appreciate your input and will review this matter as soon as possible. Please feel free to provide any additional information or context that you think may be helpful. We'll keep you updated on the progress of our review.
Hi @DebugXie , could you help provide a minimal project?