0

My situation is this:

I am building a spring boot application, when I autowire the UserRepository in the controller it initializes it and when I try to call the findByUserName method everything is OK.

UserController

@Controller    
@RequestMapping(path="/api/v1/users") 
public class UserController {

@Autowired 
private UserRepository userRepository;

@GetMapping(path="/{userName}")
public @ResponseBody AuthenticationDetails getUserByUsername(@PathVariable String userName) throws UserNotFoundException {

    User user = userRepository.findByUserName(userName);=
    ...
    }
}

After creating the controller I needed to use Spring Security to secure the paths of the controller so I added in the SecurityConfig class the following configuration:

SecurityConfig

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
public void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity.csrf().disable().authorizeRequests()
            .antMatchers(HttpMethod.POST, "/login").permitAll().anyRequest().authenticated().and()
            .addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),
                    UsernamePasswordAuthenticationFilter.class)
            .addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);

}
...
}

Now, when I try to post a request to the /login path I get a NullPointerException in the CustomAuthenticationProvider class when I try to load the data through userRepository instance by calling the findByUserName method because userRepository instance is null.

CustomAuthenticationProvider

public class CustomAuthenticationProvider implements AuthenticationProvider {

@Autowired 
private UserRepository userRepository;

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {

    User userFromRepository = userRepository.findByUserName(authentication.getName().toLowerCase()); 
    ...
}

My questions are this:

Is not the state of the beans the same during the run-time of the application? Are the beans created when the application loads right?

Why Spring Boot manages to autowire the instance with the bean in my controller and in the same application but in another class it does not autowire them?

ahmetcetin
  • 2,621
  • 1
  • 22
  • 38
Arber Hoxha
  • 73
  • 10
  • Please show your code of the userRepository. It is almost sure that you are missing @Repository annotation there, so Spring does not have a bean to autowire – Marek Urbanowicz Jun 30 '17 at 08:22
  • As I said initially it works when I autowire it in my controller so the @Repository annotation is present – Arber Hoxha Jun 30 '17 at 08:23
  • Can you share the code where you create your `CustomAuthenticationProvider`? – Leffchik Jun 30 '17 at 08:25
  • '@Repository public interface UserRepository extends CrudRepository { public User findByUserName(String username); }' – Arber Hoxha Jun 30 '17 at 08:25
  • Hi @Leffchik, you want the entire class? I have already posted the relevant code in my initial post on top. – Arber Hoxha Jun 30 '17 at 08:26
  • 2
    It's just I think maybe you create it like `new CustomAuthenticationProvider()` so it's not a spring bean and not being managed by spring context. In this case, obviously, `@Autowire` wont work – Leffchik Jun 30 '17 at 08:27
  • You have to add `@Component` on your CustomAuthenticationProvider and beans will be injected. Please check also that package of `CustomAuthenticationProvider` in subpackage of package where is your class with annotation `@SpringBootApplication` and if this package with `ComponentScan` annotation. – Krzysztof Atłasik Jun 30 '17 at 08:29
  • @Autowired public void configure(AuthenticationManagerBuilder auth) throws Exception{ auth.authenticationProvider(**new CustomAuthenticationProvider()**); } You think this is the problem? – Arber Hoxha Jun 30 '17 at 08:29
  • 1
    Yes! It is the problem. I had exactly the same issue. Autowired is not working when you create instance using new – Marek Urbanowicz Jun 30 '17 at 08:31
  • 1
    Definitely. This wont work. Your `CustomAuthenticationProvider` should be a spring bean, so it's fileds can be injected – Leffchik Jun 30 '17 at 08:31
  • OK, thank you for your replies. Kind regards – Arber Hoxha Jun 30 '17 at 08:32
  • @Leffchik reply as an answer, not as a comment, so that I can mark it as correct if you want. Thank you. – Arber Hoxha Jun 30 '17 at 08:34
  • @ArberHoxha, done. You're welcome. – Leffchik Jun 30 '17 at 08:41
  • you can return a `new` thing from a `@Bean` method within a `@Configuration` class and it will gets all the things injected, but otherwise, don't `new` things yourself. In very few very special cases you can do https://stackoverflow.com/a/3813725/995891 – zapl Jun 30 '17 at 08:44

1 Answers1

2

The problem is that you create your CustomAuthenticationProvider like this new CustomAuthenticationProvider(), so it's not really a spring bean and it's fields can not be injected. What you need to do is define CustomAuthenticationProvider bean and it will work.

Leffchik
  • 1,950
  • 14
  • 16