3

The spring boot apps starts up, tomcat runs, and then it throws an error before finally dying.

Error

Running my app gives me this Autowired error:

2016-07-29 02:18:24.737 ERROR 44715 --- [  restartedMain] o.s.boot.SpringApplication               : Application startup failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSecurityConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private myapp.MyUserDetailsService myapp.WebSecurityConfig.userDetailsService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [myapp.MyUserDetailsService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]

Details

My Security configuration:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
        http
        .authorizeRequests()
        .antMatchers("/", "/register").permitAll()
        .anyRequest().authenticated()
        .and()
        .formLogin()
        .loginPage("/")
        .permitAll()
        .and()
        .logout()
        .permitAll();
}

@Autowired
private MyUserDetailsService userDetailsService;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
}

}

MyUserDetails:

@Service
@Transactional
public class MyUserDetailsService implements UserDetailsService {

@Autowired
private UserRepository userRepository;


public MyUserDetailsService() {
        super();
}

@Override
public UserDetails loadUserByUsername(String userName)
throws UsernameNotFoundException {
        User user = userRepository.findByUserName(userName);
        if (user == null) {
                return null;
        }
        List<GrantedAuthority> auth = AuthorityUtils
                                      .commaSeparatedStringToAuthorityList("ROLE_USER");
        String password = user.getPassword();
        return new org.springframework.security.core.userdetails.User(userName, password,
                                                                      auth);
}



}

You may find full source code at Git Repo

JavaHopper
  • 5,567
  • 1
  • 19
  • 27
Amin Shah Gilani
  • 8,675
  • 5
  • 37
  • 79
  • I like the idea of sharing your code base via Git Repo url. It would be great if SO provides an optional Git Repo filed while posting the question, that way it would help to answer the question better by looking at full source – JavaHopper Jul 29 '16 at 21:07

4 Answers4

6

I've tried your project at commit 3b9a6a2e, and the error is actually different:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSecurityConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private myapp.MyUserDetailsService myapp.WebSecurityConfig.userDetailsService; nested exception is java.lang.IllegalArgumentException: Can not set myapp.MyUserDetailsService field myapp.WebSecurityConfig.userDetailsService to com.sun.proxy.$Proxy80

Which makes your question a duplicate of Spring can't create beans. Solution: replace

@Autowired
private MyUserDetailsService userDetailsService;

with

@Autowired
private UserDetailsService userDetailsService;

Your solution (removing @Transactional) works because without @Transactional there is no reason for Spring to wrap MyUserDetailsService in a proxy.

Community
  • 1
  • 1
Roman
  • 6,486
  • 2
  • 23
  • 41
  • Thank you for explaining this! Although, then how would I pass Spring know to look for my config from `MyUserDetailsService`? – Amin Shah Gilani Jul 29 '16 at 12:10
  • What does "pass Spring know" means? – Roman Jul 29 '16 at 12:15
  • I mean: How would Spring know to look for my configuration from `MyUserDetailsService`? Sorry, I make a bunch of typos when I'm typing in a hurry. – Amin Shah Gilani Jul 29 '16 at 12:19
  • You mean, how would Spring know to autowire specifically `MyUserDetailsService`? Well, it will search for all beans that implement `UserDetailsService` (the field type), and if it founds exactly one, that will be autowired, otherwise an exception will be thrown. – Roman Jul 29 '16 at 12:51
  • 1
    @Roman, +1 for forking his repo and suggesting the fix. Indeed developers love SO and Git! – JavaHopper Jul 29 '16 at 21:09
2

Removing @Transactional from MyUserDetailsService worked. No idea why. If someone has an explanation, please post and it i'll mark it as the answer.

Double checked, this really is correct, if you'd like to check for yourself, please check out commit 840f0753bdca1592d9070c74bc87f30e8e2f87a7 for the repository listed above, and test it.

And stop downvoting this answer because you think it's incorrect.

Amin Shah Gilani
  • 8,675
  • 5
  • 37
  • 79
  • 1
    That does not really make sense, any chances you did some edit in-between ? For example the changes UserF40 told you to do and when you tried them, your project was not rebuilt which is why it would not have worked ? – Jean-François Savard Jul 28 '16 at 22:01
  • @amingilani If you readd `@Transactional` and rebuild, does it still work? If so that didn't solve it. – UserF40 Jul 28 '16 at 22:06
  • @Jean-FrançoisSavard @UserF40, just checked, it doesn't work. Removing `@Transactional` makes it work. – Amin Shah Gilani Jul 28 '16 at 22:09
1

Add @ComponentScan to WebSecurityConfig.

This should wire in MyUserDetailsService due to component scanning as it is annotated with @Service.

A package name can be passed as a parameter to the annotation to set the scope of component scanning, for example:

@ComponentScan("com.company.team")
UserF40
  • 3,533
  • 2
  • 23
  • 34
1

please add Annotation: @ComponentScan("") on main configuration class.

If you want to create bean/service for specific directory then you can give package path inside @ComponentScan("package.to.scan")

user3145373 ツ
  • 7,858
  • 6
  • 43
  • 62