Null @Autowired field is a common problem in Spring and the main reason for this is, the instance, in which @Autowired is used, is not a Spring-managed instance.

Spring is a dependency injection framework and dependency injection in Spring only works with Spring-managed instances, called Beans. Hence, the @Autowired field will only get populated when Spring manages both instances, the field itself and the object in which it is getting injected too.

Example:

Let us create a simple application that should return ‘HelloWorld’. Let’s start with the service layer.

@Service
public class DemoService {

    @Autowired
    private DemoMessageUtil messageUtil;

    public String getMessage() {
        return messageUtil.beautify("HelloWorld");
    }
}

Our service layer depends on DemoMessageUtil utility class, let’s create it too:

@Component
public class DemoMessageUtil {

    public String beautify(String text) {
        return "--[" + text + "]--";
    }
}

Perfect, now we need a controller to expose a REST API for GET /message endpoint

@RestController
public class DemoController {

    private DemoService demoService;

    public DemoController() {
        this.demoService = new DemoService(); // Create an instance of DemoService
    }

    @GetMapping("/message")
    public String getMessage() {
        return demoService.getMessage();
    }
}

Run this application and call GET http://localhost:8080/message. You will get an Internal Server Error and you will find following statements in logs:

java.lang.NullPointerException: null
	at com.example.demo.service.DemoService.getMessage(DemoService.java:14) ~[classes/:na]
	at com.example.demo.controller.DemoController.getMessage(DemoController.java:18) ~[classes/:na]
	...

We got a NullPointerException in DemoService at line: return messageUtil.beautify("HelloWorld");. The messageUtil was NULL there.

But, why did this happen? We have used proper annotations like @Component, @Service, Controller.

Problem is in the constructor of DemoController:

...
public DemoController() {
        this.demoService = new DemoService(); // Create an instance of DemoService
    }
...    

Here we are creating a new instance of DemoService(), which is NOT a spring-managed instance because we created it, not the Spring context, so the Spring can’t manage this instance. That’s why @Autowired has no effect in that instance and we got a Null @Autowired field.

To solve this issue, Just remove DemoService creation. Since it is annotated by @Service, Spring will automatically create its instance and we can @Autowired the service in the controller. The updated controller would look like:

@RestController
public class DemoController {

    @Autowired
    private DemoService demoService;

    @GetMapping("/message")
    public String getMessage() {
        return demoService.getMessage();
    }
}

Run the application, and the NullPointerException will be gone.

Conclusion:

Spring dependency injection only works with Spring-managed objects or Beans. If the object in which a Bean is getting injected is not a spring managed object, you will get null @Autowired fields. To fix this, make sure only the framework create and manage the related dependencies.