Reputation: 1
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
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