Thomas Duchatelle
Thomas Duchatelle

Reputation: 385

How to debug spring dependencies order?

Behind this issue, I want to understand and debug how Spring beans are instantiated (in which order) and how dependencies are resolved.

Context

I'm using:

I added to my DAO security annotations like:

@PreAuthorize("hasRole('ROLE_ADMIN') OR hasPermission(#entity, 'save')")
<S extends T> S save(S s);

And I have a custom security configuration:

@Configuration
@Slf4j
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth, 
                              UserDetailsService userDetailsService,
                              PasswordEncoder passwordEncoder) throws Exception {
    log.info("Configuring Authentication...");
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}

Obviously, autowired beans doesn't depends on DAO which have security annotations.

It works fine if I run main method (which use Spring Boot), no matter if it's compiled jar or in my IDE). But in some case (junit tests for example), I get this exception:

java.lang.IllegalStateException: Cannot apply org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer@362b384c to already built object

I assume method AuthenticationManagerBuilder.build() has been called before Spring create and configure my SecurityConfiguration. But why? Order of WebSecurityConfigurerAdapter is set to 100, it should be done before everything else!

Question

How can I see why Spring create other beans (DAO and services) before configuration? How can I check there is no dependency from my configuration service to my services / dao?

Thanks,

Upvotes: 0

Views: 1292

Answers (1)

Dave Syer
Dave Syer

Reputation: 58094

The @Autowired method is going to be called immediately after that configuration class is instantiated (which will be triggered by the security filter being created when the web container starts). That's pretty early, but not early enough for your use case, since you need to be the first to use the AuthenticationManagerBuilder. I recommend you use a GlobalAuthenticationConfigurerAdapter (i.e. a new bean) like in the Spring Boot samples (Spring Security will look for beans of that type even earlier).

Upvotes: 1

Related Questions