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
@PersistenceContext
fields (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
@Autowired
instead 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.java
withConfiguration
annotation. This class is empty & it looks you have commented it after creating & defining beans.Spring is actually checking
PersistenceConfig.java
for 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.xml
instead of looking anywhere else. Comment outConfiguration
annotation 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.LocalSessionFactoryBean
instead oforg.springframework.orm.hibernate4.LocalSessionFactoryBean
as it will be inline with your latest spring & jpa versions.
Once you used this, you will be able to see entitymanager got created properly.