I think that the main problem is that you want to instantiate your service directly (with new
) and not with Spring:
MovieService movieService = new MovieServiceImpl();
When you do this, your MovieServiceImpl
instance is constructed but not initialised (the field @Autowired MovieDao
is null
).
If you want to instantiate properly your object with field injection, you need to use Spring. As explained in the documentation or in this example, you can automatically detect all your annotated beans and initialize them in your context with the component scanning.
Example
In your case, using annotiations on (@Component
, @Service
, etc) and in (@Autowired
, @Inject
, etc) your beans, your project could look like this:
Spring configuration app-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Use component scanning to auto-discover your beans (by annotation) and initialize them -->
<context:component-scan base-package="com.se325.a01" />
<!-- No need to declare manually your beans, because beans are auto-discovered thanks to <context:component-scan/> -->
</beans>
Entry point of your application App.java
package com.se325.a01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.se325.a01.model.Movie;
import com.se325.a01.service.MovieService;
public class App {
public static void main(String[] args) {
// Let's create the Spring context based on your app-context.xml
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"app-context.xml"});
// Now your context is ready. All beans are initialised.
// You can retrieve and use your MovieService
MovieService movieService = context.getBean("movieService");
Movie matrixMovie = new Movie("Matrix");
movieService.create(matrixMovie);
}
}
In fact, when you are using Spring, it is really important to understand how the context is initialized. In the example above, it can be sum up as:
- Your entry point
App#main
is called.
- The configuration
app-context.xml
is loaded by ClassPathXmlApplicationContext
.
- The package
com.se325.a01
is scanned thanks to the line <context:component-scan base-package="com.se325.a01" />
. All annotated beans (@Component
, @Service
, etc) are contructed but not yet initialised.
- When all the beans are constructed, Spring initialises them by injecting dependencies. In the example, the
@Autowired
annotations which mark the dependencies are also discovered thanks to the line <context:component-scan ... \>
.
- The context is ready with all beans :)
Notes
All this answer explains how you can use component scanning and annotations to use Spring in a main
entry point. However, if you are developing a server application, the entry point is the WEB-INF/web.xml
.
As @chrylis said, field injection is error prone. Prefer using constructor-based injection.