I am trying to learn creating ReST API end points using spring mvc and Hibernate without using springboot. When I am running my end point , I am getting internal server error saying that ,
java.lang.NullPointerException: Cannot invoke "javax.persistence.EntityManager.createQuery(String, java.lang.Class)" because "this.entityManager" is null.
My spring-servlet.xml file under src/main/webapp/web-1nf is like the following,
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<annotation-driven />
<resources mapping="/resources/**" location="/resources/" />
<beans:bean id="dataSource"
>
<beans:property name="driverClassName" value="org.postgresql.Driver" />
<beans:property name="url" value="jdbc:postgresql://localhost:5432/company" />
<beans:property name="username" value="postgres" />
<beans:property name="password" value="postgresql" />
<!--<property name="socketTimeout" value="10"/>-->
<beans:property name="connectionProperties">
<beans:props>
<beans:prop key="socketTimeout">10</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<beans:bean id="hibernate4AnnotatedSessionFactory"
>
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="annotatedClasses">
<beans:list>
<beans:value>com.springmvc.Employee</beans:value>
</beans:list>
</beans:property>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop
key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect
</beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<context:component-scan base-package="com.springmvc" />
<tx:annotation-driven transaction-manager="transactionMgr"/>
<beans:bean id="transactionMgr"
>
<beans:property name="entityManagerFactory" ref="mgrFactory"/>
</beans:bean>
<beans:bean id="mgrFactory" >
<beans:property name="dataSource" ref="dataSource"/>
<beans:property name="packagesToScan" value="com.springmvc"/>
<beans:property name="jpaVendorAdapter">
<beans:bean />
</beans:property>
<beans:property name="jpaProperties">
<beans:props>
<beans:prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</beans:prop>
<beans:prop key="hibernate.dialect">${hibernate.dialect}</beans:prop>
<beans:prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</beans:prop>
<beans:prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</beans:prop>
<beans:prop key="hibernate.show_sql">${hibernate.show_sql}</beans:prop>
<beans:prop key="hibernate.format_sql">${hibernate.format_sql}</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
</beans:beans>
My controller is ,
@RestController
@RequestMapping("/mvchibernate")
public class CompanyController {
@Autowired
EmployeeService employeeService;
@GetMapping(value = "/getAllEmployees")
public List<Employee> getEmployeesList() {
@SuppressWarnings("unchecked")
List<Employee> listOfEmployees = employeeService.getAllEmployees();
return listOfEmployees;
}
}
And my service class like the following,
@Service
public class EmployeeService {
@Autowired
EmployeeDAO employeeDaoObj;
public List getAllEmployees() {
return employeeDaoObj.getAllEmployees();
}
}
And DAO implementation ,
@Repository
public class EmployeeDAO {
@PersistenceContext private EntityManager entityManager;
public List<Employee> getAllEmployees() {
String jpql = "SELECT e FROM Employee e";
TypedQuery<Employee> query = entityManager.createQuery(jpql, Employee.class);
return query.getResultList();
}
}
Here in my DAO class I autowired the entitymanager.And while running I am getting Cannot invoke javax.persistence.EntityManager and last showing that because "this.entityManager" is null.
So can anyone guide me to resolve this issue or kindly refer any documentation to follow please?
CodePudding user response:
You are referencing the transactionManager bean here:
<tx:annotation-driven transaction-manager="transactionManager"/>
But the bean is actually named transactionMgr:
<beans:bean id="transactionMgr"
>
<beans:property name="entityManagerFactory" ref="MgrFactory"/>
</beans:bean>
You should reference the correct name:
<tx:annotation-driven transaction-manager="transactionMgr"/>
CodePudding user response:
I do believe there are two options:
- define PersistenceAnnotationBeanPostProcessor bean - it is responsible for injecting
@PersistenceContextfields (though documentation says it should be registered automatically, m.b. it is worth to debug it to understand the reason):
<bean />
- define EntityManager factory bean and use
@Autowiredinstead of@PersistenceContext:
<bean id="emf" >
<property name="entityManagerFactory" ref="mgrFactory"/>
</bean>
CodePudding user response:
Edit from my previous answer, After reviewing your code below is what you are currently doing:
You created
PersistenceConfig.javawithConfigurationannotation. This class is empty & it looks you have commented it after creating & defining beans.Spring is actually checking
PersistenceConfig.javafor finding configurations instead of going to your xml.Move your xml config to
src/main/resources& for supporting best practice rename it topersistence.xml.Now, you have to tell spring to read your configs from
persistence.xmlinstead of looking anywhere else. Comment outConfigurationannotation fromPersistenceConfig.java& use below code in your main class.:@SpringBootApplication @ImportResource({"classpath:persistence.xml"}) public class SpringMvcHibernateRestApiApplication {
public static void main(String[] args) { SpringApplication.run(SpringMvcHibernateRestApiApplication.class, args); }}
Also, I suggest to use
org.springframework.orm.hibernate5.LocalSessionFactoryBeaninstead oforg.springframework.orm.hibernate4.LocalSessionFactoryBeanas it will be inline with your latest spring & jpa versions.
Once you used this, you will be able to see entitymanager got created properly.
