Skip to content
Advertisement

Application Failed to start The Dependencies of some of the Beans form a cycle… Why?

so I have this section of code in AppConfig.java:

@Configuration
@EnableWebSecurity
public class AppConfig extends WebSecurityConfigurerAdapter {

    private final CurrentUserService currentUserService;
    private final SessionFilter sessionFilter;
    private final PasswordEncoder passwordEncoder;

    @Autowired
    @Lazy
    public AppConfig(CurrentUserService currentUserService, SessionFilter sessionFilter, PasswordEncoder passwordEncoder) {
        this.currentUserService = currentUserService;
        this.sessionFilter = sessionFilter;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(currentUserService).passwordEncoder(passwordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http = http.cors().and().csrf().disable();

        http = http.exceptionHandling().authenticationEntryPoint(
                (request, response, authException) -> {
                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
                }
        ).and();

        http.authorizeRequests().antMatchers("/api/login").permitAll().anyRequest().authenticated();

        http.addFilterBefore(sessionFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

if I get rid of the @Lazy it will not start, i have tried to get rid of the constructor and do:

    @Autowired
    private final CurrentUserService currentUserService;
    @Autowired
    private final SessionFilter sessionFilter;
    @Autowired
    private final PasswordEncoder passwordEncoder;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(currentUserService).passwordEncoder(passwordEncoder);
    }

same thing, can someone please help me out, I really don’t want to have to use the @Lazy Implementation. here is the error it returns:

Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'appConfig' defined in file [C:UsersBladeDocumentsWebMentmodulesbackendbuildclassesjavamaincomshortsdesignswebmentconfigurationAppConfig.class]: Unsatisfied dependency expressed through constructor parameter 2; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'appConfig': Requested bean is currently in creation: Is there an unresolvable circular reference?

When getting rid of the constructor and using field injection it gives me this error:

Error creating bean with name 'appConfig': Unsatisfied dependency expressed through field 'passwordEncoder'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'appConfig': Requested bean is currently in creation: Is there an unresolvable circular reference?

Advertisement

Answer

This error occurs because you’re creating the PasswordEncoder in the same class that you’re injecting it.

The best solution is to not autowire the PasswordEncoder (or the CurrentUserService) at all.

It appears those instances are only used in the configure(AuthenticationManagerBuilder auth) method, which is redundant.

Registering a PasswordEncoder and UserDetailsService as a bean is enough for Spring Security to detect them and use them in your configuration.

In other words, you should remove the following code:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(currentUserService).passwordEncoder(passwordEncoder);
}

The application will still behave in the exact same way.

Advertisement