Home > Back-end >  java.lang.NullPointerException: Cannot invoke "javax.persistence.EntityManager error in Spring
java.lang.NullPointerException: Cannot invoke "javax.persistence.EntityManager error in Spring

Time:07-26

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:

  1. 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 />
  1. 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:

  1. You created PersistenceConfig.java with Configuration annotation. This class is empty & it looks you have commented it after creating & defining beans.

  2. Spring is actually checking PersistenceConfig.java for finding configurations instead of going to your xml.

  3. Move your xml config to src/main/resources & for supporting best practice rename it to persistence.xml.

  4. Now, you have to tell spring to read your configs from persistence.xml instead of looking anywhere else. Comment out Configuration annotation from PersistenceConfig.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);
     }
    

    }

  5. Also, I suggest to use org.springframework.orm.hibernate5.LocalSessionFactoryBean instead of org.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.

  • Related