I’m trying to use JPA’s Context Injection. Currently my code fails to have the context injected, throwing a NullPointerException:
Exception in thread “main”
java.lang.NullPointerException at
learn.spring.dao.ListingDao.findById(ListingDao.java:19)
Below is my code, anyone see what is wrong/missing? Thanks.
Spring Configuration xml:
<beans ....>
<tx:annotation-driven />
<context:annotation-config />
<aop:aspectj-autoproxy />
<bean id="listingDao" class="learn.spring.dao.ListingDao" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://xxx.xxx.xxx.xxx/xxxxx" />
<property name="username" value="xxxxxx" />
<property name="password" value="xxxxxx" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="learnSpring" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
...
</beans>
DAO class:
package learn.spring.dao;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.transaction.annotation.Transactional;
import learn.spring.model.Registration;
@Transactional
public class ListingDao {
public ListingDao() {}
@PersistenceContext
private EntityManager entityManager;
public Registration findById(int id) {
Query query = entityManager.createQuery("FROM Registration r WHERE r.memberId = ?1");
query.setParameter(1, id);
return (Registration) query.getSingleResult();
}
}
peristence.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="learnSpring" />
</persistence>
Class w/ “main” method:
public class Performance {
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("learn-spring.xml");
Performer performer = (Performer) context.getBean("musician");
performer.perform();
ListingDao listingDao = new ListingDao();
Registration registration = listingDao.findById(1);
System.out.println("Member id = " + registration.getMemberId() + " Name = " + registration.getFirstName() + " " + registration.getLastName());
}
}
Your problem is that your
ListingDaoisn’t part of the spring context.All the classes which you want to benefit from the spring’s dependecy injection must be instantiated by spring. When you instantiate your
ListingDaowith thenewoperator, your object isn’t part of the spring context and it doesn’t receive an automaticEntityManager.So the solution would be to get the
ListingDaofrom the context, like you did with the performer:As a sidenote – avoid accessing the spring context directly. i.e. avoid lines like the above. Use annotations to inject your dependencies, rather than requesting them, because you are thus turning a Dependency Injection framework into a Service Locator.