Reputation: 9201
This is a Spring Boot question, and is thus different from other postings such as this one which cover the same error message in different contexts. How do I resolve the error below in a way that enables a custom user details service to be autowired to the spring boot app shown below?
The error being thrown when I type mvn spring-boot:run
is:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [demo.UiApplication$UserRepository] found
for dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations: {}
The location in the code below that the error points to is:
@Repository
interface UserRepository extends CrudRepository<User, Long> {
User findByName(String name);
}
The complete code for this very simple test app is:
@SpringBootApplication
@Controller
public class UiApplication extends WebMvcConfigurerAdapter {
// Match everything without a suffix (so not a static resource)
@RequestMapping(value = "/{[path:[^\\.]*}")
public String redirect() {
// Forward to home page so that route is preserved.
return "forward:/";
}
@RequestMapping("/user")
@ResponseBody
public Principal user(Principal user) {
return user;
}
public static void main(String[] args) {
SpringApplication.run(UiApplication.class, args);
}
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
slr.setDefaultLocale(Locale.US);
return slr;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci;
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
@Bean
public SecurityConfiguration applicationSecurity() {
return new SecurityConfiguration();
}
@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
protected static class AuthenticationSecurity extends
GlobalAuthenticationConfigurerAdapter {
@Autowired
private Users users;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(users);
}
}
@SuppressWarnings("deprecation")
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().authorizeRequests()
.antMatchers("/index.html", "/", "/login", "/message", "/home")
.permitAll().anyRequest().authenticated().and().csrf()
.csrfTokenRepository(csrfTokenRepository()).and()
.addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
}
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie == null || token != null
&& !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
@Service
class Users implements UserDetailsService {
private UserRepository repo;
@Autowired
public Users(UserRepository repo) {
this.repo = repo;
}
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = repo.findByName(username);
if (user == null) {
return null;
}
List<GrantedAuthority> auth = AuthorityUtils
.commaSeparatedStringToAuthorityList("ROLE_USER");
if (username.equals("admin")) {
auth = AuthorityUtils
.commaSeparatedStringToAuthorityList("ROLE_ADMIN");
}
String password = user.getPassword();
return new org.springframework.security.core.userdetails.User(username, password,
auth);
}
}
@Controller
@Repository
interface UserRepository extends CrudRepository<User, Long> {
User findByName(String name);
}
@Entity
class User {
@GeneratedValue
@Id
private Long iduser;
private String name;
private String password;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
private Collection<SessionLog> sessionLogCollection;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
@Entity
class SessionLog {
@GeneratedValue
@Id
private Long id;
private String sessionid;
@ManyToOne(optional = true)
@JoinColumn(name = "iduser")
private User user;
public String getSessionid(){
return sessionid;
}
}
}
The boot log from the CentOS 7 terminal is very long, but the last element is:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [demo.UiApplication$UserRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 38 more
Upvotes: 0
Views: 3344
Reputation: 153
If your Entity classes in different package you need to add following annotations. look at this answer may be helpful link
@EntityScan("Entity.package")
@EnableJpaRepositories("repository.package")
Upvotes: 1
Reputation: 2022
Your UserRepository
is a nested interface, tell spring you want that interface to be discovered
@SpringBootApplication
@Controller
@EnableJpaRepositories(basePackages = "demo", considerNestedRepositories = true)
public class UiApplication extends WebMvcConfigurerAdapter {
Upvotes: 2
Reputation: 10547
You are missing
@EnableJpaRepositories("your.package")
annotation...
@SpringBootApplication
@Controller
@EnableJpaRepositories("your.package")
public class UiApplication extends WebMvcConfigurerAdapter {
....
}
Upvotes: 1
Reputation: 20885
It means you should provide a bean of type UserRepository
. The message is issued by the container when it tries to construct (inject) a Users
: looking at the constructor marked with @Autowired
, the container searches a UserRepository
bean in your configuration, but none is found and a fatal error is thrown.
You can do it by adding a provider method into one of your @Configuration
classes:
@Bean
public UserRepository userRepository(DataSource dataSource) {
return new UserRepositoryImpl(dataSource);
}
or directly by annotating the required class with @Service
(or any equivalent stereotype annotation)
Upvotes: 0