Search code examples
javaspringspring-mvcspring-securitycomponent-scan

Spring mvc hide one package from others


here is my project structure

As it can be seen in picutre, my ComponentScan is set to whole project. But somehow 'config' package doesn't see any other package and vice versa.

If I run my project, i get an error on startup that No qualifying bean of type 'com.rjproject.dao.UserDao' available, and the same for all other beans, that autowired in this package. But they autowiring perfectly fine in all other packages.

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webSecurityConfig': Unsatisfied dependency expressed through field 'myUserDetailsService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.rjproject.service.MyUserDetailsService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

But this bean exists and autowires fine in any other package.

here webSecurityConfig

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    MyUserDetailsService myUserDetailsService;

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests().antMatchers("/admin/**")
                .access("hasRole('ADMIN')").and().formLogin()
                .loginPage("/login").failureUrl("/login?error")
                .usernameParameter("username")
                .passwordParameter("password")
                .and().logout().logoutSuccessUrl("/login?logout")
                .and().csrf()
                .and().exceptionHandling().accessDeniedPage("/403");
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        return encoder;
    }
}

and here MyUserDetailService

@Service
public class MyUserDetailsService implements UserDetailsService {

@Autowired
private UserDao userDao;

@Transactional(readOnly=true)
@Override
public UserDetails loadUserByUsername(final String username)
        throws UsernameNotFoundException {

    com.rjproject.entities.User user = userDao.findByUserName(username);
    List<GrantedAuthority> authorities =
            buildUserAuthority(user.getAuthorities());

    return buildUserForAuthentication(user, authorities);

}

private User buildUserForAuthentication(com.rjproject.entities.User user,
                                        List<GrantedAuthority> authorities) {
    return new User(user.getUsername(), user.getPassword(),
            user.isEnabled(), true, true, true, authorities);
}

private List<GrantedAuthority> buildUserAuthority(Set<Authorities> userRoles) {

    Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();

    // Build user's authorities
    for (Authorities userRole : userRoles) {
        setAuths.add(new SimpleGrantedAuthority(userRole.getAuthority()));
    }

    List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);

    return Result;
}

}

UPD

As i figured out, the problem is that spring beans doesn't created already when i want to autowire it in config. But every online example says that it should work.


Solution

  • It doesn't hide. You just need to set @ComponentScan annotation to all of your config classes. Each config class should have its own @ComponentScan