Unsatisfied dependency expressed through field 'userDetailsService'; NoSuchBeanDefinitionException: 'org.springframework.securityUserDetailsService'

Viewed 817

It seems that Spring can't autowire the UserDetailsService. I don't understand why.

WebConfig.java:

@Configuration
@ComponentScan("testproject")
@EnableWebMvc
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "testproject",
        entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager")
 public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureDefaultServletHandling(
                DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
    }

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver bean = new InternalResourceViewResolver();

        bean.setViewClass(JstlView.class);
        bean.setPrefix("/WEB-INF/view/");
bean.setSuffix(".html");


        return bean;
    }

    @Bean
    public UserDetailsService userDetailsService()  {
        UserDetailsService userDetailsService =
                new UserDetailsServiceImpl();
        return userDetailsService;
    }
}

MyAppInitializer.java:

public class MyAppInitializer extends
                AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    public void onStartup(final ServletContext sc) throws ServletException {
        System.out.println("onStartup!");

        AnnotationConfigWebApplicationContext root =
                new AnnotationConfigWebApplicationContext();

        root.register(WebConfig.class);
        root.setServletContext(sc);

        root.scan("testproject");
        sc.addListener(new ContextLoaderListener(root));

        ServletRegistration.Dynamic appServlet =
                sc.addServlet("dispatcher", new DispatcherServlet(new GenericWebApplicationContext()));
        appServlet.setLoadOnStartup(1);
        appServlet.addMapping("/");
    }

        @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] {SecurityConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

SecurityConfig.java:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter  {
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private JwtRequestFilter jwtRequestFilter;
    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;


    @Bean
    DaoAuthenticationProvider authenticationProvider(){
        DaoAuthenticationProvider daoAuthenticationProvider =
                new DaoAuthenticationProvider();
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        daoAuthenticationProvider.setUserDetailsService(this.userDetailsService);
        return daoAuthenticationProvider;
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring();
    }
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    @Autowired
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.csrf().disable()
                // dont authenticate this particular request
              //  .authorizeRequests().antMatchers("/login").permitAll()
                // all other requests need to be authenticated
                .authorizeRequests().anyRequest().authenticated().and()
                .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        // Add a filter to validate the tokens with every request
        httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
    }


    @Bean
    BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

SecurityWebApplicationInitializer.java:


public class SecurityWebApplicationInitializer extends
                    AbstractSecurityWebApplicationInitializer {
    public SecurityWebApplicationInitializer() {
        super(SecurityConfig.class);
    }
}

Full error:

Error creating bean with name 'securityConfig': 
Unsatisfied dependency expressed through field 'userDetailsService'; nested exception is 
org.springframework.beans.factory.NoSuchBeanDefinitionException:
 No qualifying bean of type 
'org.springframework.security.core.userdetails.UserDetailsService' 
available: expected at least 1 bean which qualifies as autowire candidate. 
Dependency annotations: 
{@org.springframework.beans.factory.annotation.Autowired(required=true)}

Any help is appreciated!

EDIT:

UserDetailsServiceImpl.java:

@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService  {
    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException  {
        User user = userRepository.findByUsername(username);
        if (user != null) {
            return new UserDetailsImpl(user);
        } else {
            throw new UsernameNotFoundException("User not found.");
        }
    }
}
1 Answers

Your @ComponentScan should point to the package of the classes, I'm assuming testproject is not the package name.

Related