Announcement Announcement Module
Collapse
No announcement yet.
PersistenceContext not injected without @Transactional Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • PersistenceContext not injected without @Transactional

    Hello friends,

    I have a typical service-DAO-Hibernate model application running. Things worked perfectly till a friend questioned my usage of @Transactional annotation for a simple getter method. Leaving aside design philosophies, I tried out a small project where I had no @Transactional annotation on a find method. With my DAO having a @PersistenceContext injection, I would expect Spring to inject in the EntityManager and manage it through the query execution. But apparently I was wrong.

    I have referred to the petclinic example also but dont see anything revealing there.

    Here is my Spring configuration:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
    		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    		xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    		xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee"
    		xmlns:tx="http://www.springframework.org/schema/tx"
    		xsi:schemaLocation="
    			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
    			http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
    			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    
    	
    	<bean id="jdbc.datasource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="true">
    		<property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver" />
    		<property name="url" value="jdbc:db2://10.21.22.1:50001/TESTU8:retrieveMessagesFromServerOnGetMessage=true;"/>
    		<property name="username" value="DB2User" />
    		<property name="password" value="passme" />
       </bean>
    
          <bean id="entityManagerFactory" 
    		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="jdbc.datasource" />
            <property name="persistenceUnitName" value="sattest" />
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" >
                	<property name="showSql" value="true" />
                	<property name="databasePlatform" value="org.hibernate.dialect.DB2Dialect" />
                	<property name="generateDdl" value="false" />
                </bean>
            </property>
    		<property name="jpaPropertyMap">
    			<map>
    				<entry key="javax.persistence.transactionType" value="RESOURCE_LOCAL" />
    			</map>
    		</property>
    	</bean>
    
    	<bean
    		class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
    
    	<bean id="transactionManager"
    		class="org.springframework.orm.jpa.JpaTransactionManager" >
    		<property name="entityManagerFactory" ref="entityManagerFactory" />
            <property name="dataSource" ref="jdbc.datasource" />
    	</bean>
    
    	<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="false" />
    	
    	<context:annotation-config/>
    	
    	<bean id="basicDao" class="com.sathya.basic.BasicDAO" />
    	
    	<bean id="basicService" class="com.sathya.basic.BasicServiceImpl" >
    		<property name="dao" ref="basicDao" />
    	</bean>
    </beans>
    My Service interface:

    Code:
    package com.sathya.basic;
    
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    public interface IBasicService {
    
    	@Transactional(propagation=Propagation.REQUIRED, readOnly=false)
    	Book createBook(String name);
    	
    	Book[] findBooksMatchingName(String name);
    }
    and my DAO:

    Code:
    package com.sathya.basic;
    
    public class BasicDAO {
       @PersistenceContext
       protected EntityManager entityManager;
    
       public Book createBookBook book){
    	entityManager.persist(book);
    	return book;
        }
    
       public List<Book> findBooksByName(String name) {
    	String queryStr = "select b from " + Book.class.getName() + " b where b.name=:name";
    
             query = entityManager.createQuery(queryStr);         
            query.setParameter("name", name);
    
          return (List<Book>) query.getResultList();
       }
    Since the insert happens in a transaction mode, the creation goes through fine. But for a select, as there is no transaction, the below exception is thrown:

    Code:
    Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.SessionException: Session is closed!
    	at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:614)
    	at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:76)
    	at com.sathya.basic.BasicDAO.findBooksByName(BasicDAO.java:41)
    	at com.sathya.basic.BasicServiceImpl.findBooksMatchingName(BasicServiceImpl.java:27)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:79)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.lang.reflect.Method.invoke(Method.java:618)
    	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)
    	at $Proxy13.findBooksMatchingName(Unknown Source)
    	at com.sathya.basic.BasicTestRunner.main(BasicTestRunner.java:19)
    Caused by: org.hibernate.SessionException: Session is closed!
    	at org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:72)
    	at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1137)
    	at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
    	at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:67)
    	... 10 more
    Is a @Transactional attribute then mandatory for the EntityManager to get injected? Is there any configuration I could do so that Spring could create the entityManager on demand and close if at the end of the operation?

    Thanks.
Working...
X