CodeMed
CodeMed

Reputation: 9201

No bean qualifies as autowire candidate for this dependency

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

Answers (4)

prabath
prabath

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

KSTN
KSTN

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 {

See : http://docs.spring.io/spring-data/jpa/docs/1.6.0.RELEASE/api/org/springframework/data/jpa/repository/config/EnableJpaRepositories.html#considerNestedRepositories()

Upvotes: 2

Betlista
Betlista

Reputation: 10547

You are missing

@EnableJpaRepositories("your.package")

annotation...

@SpringBootApplication
@Controller
@EnableJpaRepositories("your.package")
public class UiApplication extends WebMvcConfigurerAdapter {
    ....
}

Upvotes: 1

Raffaele
Raffaele

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

Related Questions