amingilani amingilani - 4 months ago 103
Java Question

Autowire doesn't work for custom UserDetailsService in Spring Boot

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

Answer

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.

Comments