Creating a custom Bean
of type OAuth2AuthorizedClientManager
inside a class extending WebSecurityConfigurerAdapter
and injection this bean somewhere in the application creates a circular reference.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService oAuth2AuthorizedClientService) {
OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.refreshToken()
.build();
AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager(
clientRegistrationRepository, oAuth2AuthorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
}
@Service
public class MyBean {
private final OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager;
@Autowired
public MyBean(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
this.oAuth2AuthorizedClientManager = oAuth2AuthorizedClientManager;
}
}
How to reproduce?
- Download https://github.com/knoobie/spring-2.5-oauth2manager-demo
- Compile the application with
mvn clean install
- Test failed
Log
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myBean' defined in file [/home/knoobie/projects/bugs/spring-2.5-security-demo/target/classes/com/example/demo/MyBean.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfig': Unsatisfied dependency expressed through method 'setContentNegotationStrategy' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration': Unsatisfied dependency expressed through method 'setConfigurers' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration$OAuth2ClientWebMvcSecurityConfiguration': Unsatisfied dependency expressed through method 'setAuthorizedClientManager' parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'authorizedClientManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfig': Unsatisfied dependency expressed through method 'setContentNegotationStrategy' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration': Unsatisfied dependency expressed through method 'setConfigurers' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration$OAuth2ClientWebMvcSecurityConfiguration': Unsatisfied dependency expressed through method 'setAuthorizedClientManager' parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'authorizedClientManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration': Unsatisfied dependency expressed through method 'setConfigurers' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration$OAuth2ClientWebMvcSecurityConfiguration': Unsatisfied dependency expressed through method 'setAuthorizedClientManager' parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'authorizedClientManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration$OAuth2ClientWebMvcSecurityConfiguration': Unsatisfied dependency expressed through method 'setAuthorizedClientManager' parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'authorizedClientManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'authorizedClientManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
Workaround:
- Create the
OAuth2AuthorizedClientManager
bean in another class annotated with@Configuration
.
Comment From: wilkinsona
Thanks for the sample.
Your SecurityConfig
extends WebSecurityConfigurerAdapter
which means that a ContentNegotiationStrategy
bean should be injected into it. This bean is defined by Boot's EnableWebMvcConfiguration
due to it sub-classing WebMvcConfigurationSupport
which defines mvcContentNegotiationManager
. To allow EnableWebMvcConfiguration
to define this bean, it must be initialized and this requires the injection of any WebMvcConfigurer
beans. OAuth2ClientWebMvcSecurityConfiguration
is a WebMvcConfigurer
so it needs to be initialized and this requires the injection of any OAuth2AuthorizedClientManager
beans. Your SecurityConfig
defines a OAuth2AuthorizedClientManager
bean so it needs to be initialized but its initialization is already in progress. This is a circular reference so initialization fails.
I don't think there's anything that we can do about this in Spring Boot. Defining OAuth2AuthorizedClientManager
in another @Configuration
class is a good solution. Alternatively, I believe it would also work if the @Bean
method was declared static
as this would allow the OAuth2AuthorizedClientManager
bean to be created without SecurityConfig
having to be initialized.
You may also want to raise a Spring Security issue to see if they can remove some of the interdependencies between components so that user code is less likely to inadvertently create a circular reference.
Comment From: knoobie
Thanks @wilkinsona for your explanation!