harigon
harigon

Reputation: 1

Autowired field is null in RestController

I have a project with several modules and my aim is to reuse the services defined in the 'core' module in other modules. For exemple the module 'batch' is able to reuse the methods defined in the 'core' module (declared as @Autowired) by loading the application context class (via AnnotationConfigApplicationContext) which loads and wires the 'core' services. So far so good.

The problem arise when I want to do the same thing in my 'rest controller' module. The 'core' service is declared as @Autowired just as in the 'batch' module, but when the controller tries to use it the following exception is shown:

java.lang.NullPointerException itix.rest.itixrestservice.RestRessourceController.getRealMethod(RestRessourceController.java:40) sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:498) org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144)

The thing I have not get yet, which I think is the reason for the failure, is how to load the application context (and so wire my services) in the 'rest controller' context.

This 'rest controller' module just need to expose some endpoints, the view part is delegated to another module which will retrieve and display the endpoint contents. Controller code is as following :

@Component 
@ComponentScan(basePackages = {"itix.core.service","itix.rest.itixrestservice"}) 
@Path("/controller") 
public class RestRessourceController extends AnnotationConfigApplicationContext {

@Autowired
MatchService matchService;

@GET
@Path("getReal")
@Produces(MediaType.APPLICATION_JSON)
public ResponseEntity<List<Match>> getReal() {
    List<Match> allMatches = matchService.getAllMatches();
    return ResponseEntity.ok(allMatches);
}

The service is declared as follows:

@Service 
@Transactional(readOnly = true) public class MatchServiceImpl implements MatchService {

@Autowired
MatchDao matchDao;

and the dao :

@Repository public class MatchDaoImpl implements MatchDao {

@Autowired
private SessionFactory sessionFactory;

And this is the call to the controller which raises the error:

http://localhost:8889/itix-rest-service/rest/controller/getReal

By the way the same call to a different method which does not call the autowired service works fine.

I have found some infos using spring MVC but this is not I want to achieve. What am I missing ? Is there any link I should look at ?

Upvotes: 0

Views: 729

Answers (1)

roookeee
roookeee

Reputation: 1818

(disclaimer: I am working with the info that is given).

By default @Autowired MatchService matchService should never result in a NullPointerException in Spring as the default behaviour of @Autowired is to be non-optional - a BeanNotFoundException should have been raised.

This is showing that @Autowired is not working at all in your controller class. Looking at your controller which is using @ComponentScan and extends AnnotationConfigApplicationContext I would guess you are mixing your controller and main Spring Boot class which can't work. The main Spring Boot class cannot @Autowire beans as it's used to initialize Spring Boot itself and thus is not a managed bean.

Removing the @ComponentScan and extends AnnotationConfigApplicationContext and moving to a separate main class should solve your issues:

@SpringBootApplication
@ComponentScan(basePackages = {"itix.core.service","itix.rest.itixrestservice"}) 
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

The solution should be similiar even if you are not using Spring Boot - don't mix your controller and AnnotationConfigApplicationContext class.

Upvotes: 1

Related Questions