Two reasons why your Spring @Autowired component is null
By Steve Claridge on 2017-11-17.
The Spring framework makes heavy use of Inversion of Control (IoC) to let you inject classes without having to worry about their scope, lifetime or cleanup.
A common error people hit is when they autowire a class and when they try to call a method on it find that it is null and they get a NullPointerException
. So why didn't Spring auto-wire your class for you? Here's two possible reasons:
You instantiated the a class manually
Hi, 2005 called and asked for their code back. Yeah, OK, IoC is like the cool kid on the block and if you are using Spring then you need to be using it all the time. Here's a code snippet of a Controller
, Service
and Repository
that will result in a NullPointerException
.
@Controller
public class Controller {
@GetMapping("/example")
public String example() {
MyService my = new MyService();
my.doStuff();
}
}
@Service
public class MyService() {
@Autowired
MyRepository repo;
public void doStuff() {
repo.findByName( "steve" );
}
}
@Repository
public interface MyRepository extends CrudRepository<My, Long> {
List<My> findByName( String name );
}
This will throw a NullPointerException
in the service class when it tries to access the MyRepository auto-wired Repository, not because there is anything wrong with the wiring of the Repository but because you instantiated MyService() manually with MyService my = new MyService()
. To fix this auto-wire the Service as well:
@Controller
public class Controller {
@Autowired
MyService service;
@GetMapping("/example")
public String example() {
service.doStuff();
}
}
@Service
public class MyService() {
@Autowired
MyRepository repo;
public void doStuff() {
repo.findByName( "steve" );
}
}
@Repository
public interface MyRepository extends CrudRepository<My, Long> {
List<My> findByName( String name );
}
You forgot to annotate a class as a Component or one of its descendants
Spring uses component scanning to find the classes that it needs to auto-wire and insert into classes for IoC. Basically, Spring is going to scan the project's classpath (or paths you specified), find all of the @Component
classes and make them available for auto-wiring. So if you forget to annotate a class it will not be auto-wired and when you try and use it you will get a null and a NullPointerException
.
@Service
, @Repository
and @Controller
are all specializations of @Component
, so any class you want to auto-wire needs to be annotated with one of them. So auto-wiring this will cause a null:
public class MyService {
public void doStuff() {
}
}
but this will work fine
@Service
public class MyService {
public void doStuff() {
}
}