Announcement Announcement Module
Collapse
No announcement yet.
Spring JPA + Toplink = closed EntityManager Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring JPA + Toplink = closed EntityManager

    I'm trying to add JPA to an existing application that uses a combination of plain jsp and Spring MVC. It appears from my log file that the connection is successful, but I'm getting an "Attempting to execute an operation on a closed EntityManager." exception. When I hit the controller that calls the page in question, I see the following in the log

    Catalina.out
    Code:
    [TopLink Info]: 2007.12.13 03:33:35.390--ServerSession(2870450)--TopLink, version: Oracle TopLink Essentials - 9.1 (Build b31)
    [TopLink Info]: 2007.12.13 03:33:36.796--ServerSession(2870450)--file:/C:/dev/ident/www_ident_ws/exploded/WEB-INF/classes/-WebEnabledPU-qa login successful
    I'd appreciate any suggestions; here's my code:

    xxx-servlet.xml
    Code:
    <beans>
    ...
        <!-- post-processors for all standard config annotations -->
        <context:annotation-config/>
    
        <!-- For Exception translation -->
        <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
    
        <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
        
        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
            <property name="persistenceUnitName" ref="MyPU"/>
        </bean>
    
        <bean id="newPatientFormSignInController" class="ident.doctorsWs.questionnaire.web.NewPatientFormSignInController">
            <property name="commandClass" value="ident.entity.Questionnaire"/>
            <property name="questionnaireDao" ref="questionnaireDao"/>
        </bean>
    
        <bean id="questionnaireDao" class="ident.doctorsWs.questionnaire.dao.QuestionnaireDaoImpl"/>
    
    </beans>
    QuestionnaireDaoImpl.java
    Code:
    import org.springframework.dao.DataAccessException;
    
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import java.util.List;
    
    public class QuestionnaireDaoImpl implements QuestionnaireDao {
    
        @PersistenceContext
        private EntityManager em;
    
        public List getQuestionnairesByPracticeId(Integer practiceId) throws DataAccessException {
            return em.createQuery("select q from Questionnaire as q where q.practiceId = :practiceId")
                    .setParameter("practiceId", practiceId).getResultList();
        }
    }
    persistence.xml
    Code:
    <persistence-unit name="MyPU" transaction-type="RESOURCE_LOCAL">        <provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
            <class>ident.entity.Questionnaire</class>
            <exclude-unlisted-classes>true</exclude-unlisted-classes>
            <properties>
                <property name="toplink.jdbc.user" value="secret"/>
                <property name="toplink.jdbc.password" value="secret"/>
                <property name="toplink.jdbc.url" value="jdbc:myJdbcString"/>            
                <property name="toplink.jdbc.driver" value="com.inet.pool.PoolDriver"/>
            </properties>
        </persistence-unit>
    Here is the Stack Trace that is thrown:
    Code:
    java.lang.IllegalStateException: Attempting to execute an operation on a closed EntityManager.
    	at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerImpl.verifyOpen(EntityManagerImpl.java:567)
    	at oracle.toplink.essentials.internal.ejb.cmp3.EJBQueryImpl.setParameter(EJBQueryImpl.java:186)
    	at ident.doctorsWs.questionnaire.dao.QuestionnaireDaoImpl.getQuestionnairesByPracticeId(QuestionnaireDaoImpl.java:29)
    	at ident.doctorsWs.questionnaire.web.NewPatientFormSignInController.showForm(NewPatientFormSignInController.java:39)
    	at org.springframework.web.servlet.mvc.AbstractFormController.showNewForm(AbstractFormController.java:338)
    	at org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:278)
    	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
    	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:874)
    	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:808)
    	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:476)
    	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:431)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
    	at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:199)
    	at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:282)
    	at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:754)
    	at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:684)
    	at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:876)
    	at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
    	at java.lang.Thread.run(Thread.java:595)

  • #2
    I'm not sure that's the solution, but can't hurt to try:
    * Add the OpenEntityManagerInViewFilter/Interceptor
    * Use @PersistenceContext(PersistenceContextType.EXTENDE D)

    Gabriel

    Comment


    • #3
      Hi.
      @Gabriel: I think that the two hints you gave are kinda exclusive: one uses the one or the other, but not the two :-)

      @SpringFreeze: Seems like you haven't declared any transactions in your code.
      Try adding @Transactional to your DAO and a transaction manager in your spring config file:
      HTML Code:
      <bean id="transactionManager"
      		class="org.springframework.orm.jpa.JpaTransactionManager"
      		p:entityManagerFactory-ref="entityManagerFactory" />
      Regards.

      Comment


      • #4
        Same problem here

        Got a similar problem, using Spring 2.5.4 and dependencies included with the distribution - the stack trace:

        Code:
        Exception in thread "main" java.lang.IllegalStateException: Attempting to execute an operation on a closed EntityManager.
        	at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerImpl.verifyOpen(EntityManagerImpl.java:577)
        	at oracle.toplink.essentials.internal.ejb.cmp3.EJBQueryImpl.setParameter(EJBQueryImpl.java:225)
        	at is.cofus.amr.cimart.CIMartDAO.getXnumberOfSalesFactRecords(CIMartDAO.java:150)
        	at is.cofus.amr.jms.testing.DMWriterClient.setUpTransaction(DMWriterClient.java:54)
        	at is.cofus.amr.jms.testing.DMWriterClient.main(DMWriterClient.java:38)
        This happens when run from Java SE main(), but everything works fine when run as an 'AbstractJpaTests'. I use -javaagent:C:\lib\spring-framework-2.5.4\dist\weaving\spring-agent.jar as an VM argument when running within Eclipse. Things look very straightforward, but here is the class with the main():

        Code:
        package is.cofus.amr.jms.testing;
        
        import is.cofus.amr.cimart.CIMartServices;
        import is.cofus.amr.cimart.CustomerDim;
        import is.cofus.amr.cimart.SalesFact;
        import is.cofus.ci.beans.ArrayOfItemLine;
        import is.cofus.ci.beans.ItemLine;
        import is.cofus.ci.beans.PosTransaction;
        
        import java.io.IOException;
        import java.math.BigDecimal;
        import java.util.List;
        
        import org.springframework.context.ApplicationContext;
        import org.springframework.context.support.ClassPathXmlApplicationContext;
        import org.springframework.jms.core.JmsTemplate;
        import org.springframework.transaction.annotation.Transactional;
        
        
        public class DMWriterClient {
        	
        
        	CIMartServices cis; 
        	public void setCimartServices(CIMartServices cis) {
        		this.cis = cis; 
        	}
        	
            public static void main(String[] args) throws IOException {
            	DMWriterClient dmwc = new DMWriterClient();
            	
                ApplicationContext context = new ClassPathXmlApplicationContext(
                        "classpath:/is/cofus/amr/jms/resources/client-context.xml");
                JmsTemplate jmsTemplate = (JmsTemplate) context.getBean("jmsTemplate");
                dmwc.setCimartServices((CIMartServices) context.getBean("cimartServices")); 
        
                jmsTemplate.setMessageIdEnabled(true);
        
                PosTransaction posTrx = dmwc.setUpTransaction(); 
                
                System.out.println("Sending message carrying the following pos trx:\n " 
                		+ posTrx.toString());
         
        
                jmsTemplate.convertAndSend(posTrx);
        
                System.out.println("Message sent");
        
            }
            
            @Transactional(readOnly = true)
        	private PosTransaction setUpTransaction() {
        
        		
        		List<SalesFact> sfList1 = cis.getXnumberOfSalesFactRecords(10,
        				new BigDecimal(5000));
        
        		// transaction #1 - the birthday customer
        		PosTransaction posTrx1;
        		posTrx1 = generatePosTransaction(sfList1.get(0));
        
        		CustomerDim cust = cis.findOneCustomerWhoHasBirthdayThisWeek();
        		posTrx1.setLoyaltyId(cust.getLoyaltyId());
        
        		return posTrx1; 
        	}
        The Spring context XML for the JPA stuff is as following:

        [CODE]
        Code:
        <?xml version="1.0" encoding="UTF-8"?>
        <beans xmlns="skipping this since I'm not allowed to include URL's>
        	<context:annotation-config/>
        	<context:component-scan base-package="is.cofus.amr" />
        	<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
        	<bean id="ruleEngine" class="is.cofus.amr.rulengine.RuleEngine">
        		<property name="cmpgnServices"> <ref bean ="cmpgnServices"/></property>
        		<property name="ruleServices"> <ref bean ="ruleServices"/></property>
        		<property name="cimartServices"> <ref bean ="cimartServices"/></property>
        	</bean>
        	<bean id="mgmtServices" class="is.cofus.amr.mgmt.MgmtDAO">
        		<property name="entityManagerFactory" ref="entityManagerFactory" />
        	</bean>
        	<bean id="ruleServices" class="is.cofus.amr.rules.RuleDAO">
        		<property name="entityManagerFactory" ref="entityManagerFactory" />
        	</bean>
        	<bean id="cmpgnServices" class="is.cofus.amr.cmpgn.CampaignDAO">
        		<property name="entityManagerFactory" ref="entityManagerFactory" />
        		<property name="mgmtServices" ref="mgmtServices" />
        
        		<property name="ruleServices" ref="ruleServices" />
        	</bean>
        	<bean id="cimartServices" class="is.cofus.amr.cimart.CIMartDAO">
        		<property name="entityManagerFactory" ref="entityManagerFactory" /> 
        	</bean>
        	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
        		<property name="dataSource" ref="dataSource" />
        		<property name="jpaVendorAdapter">
        			<bean
        				class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter">
        				<property name="showSql" value="false" />
        				<property name="generateDdl" value="false" />
        				<property name="databasePlatform"
        					value="oracle.toplink.essentials.platform.database.DB2Platform" />
        			</bean>
        		</property>
        		<property name="loadTimeWeaver">
        			<bean
        				class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
        		</property>
        	</bean>
        	<bean id="dataSource"
        		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        		<property name="driverClassName"
        			value="com.ibm.db2.jcc.DB2Driver" />
        		<property name="url" value="jdbc:db2://localhost:50000/ntcmin" />
        		<property name="username" value="db2admin" />
        		<property name="password" value="xxxxx" />
        	</bean>
        	<bean id="transactionManager"
        		class="org.springframework.orm.jpa.JpaTransactionManager">
        		<property name="entityManagerFactory"
        			ref="entityManagerFactory" />
        		<property name="dataSource" ref="dataSource" />
        	</bean>
        
        </beans>
        The DAO class extends JpaDaoSupport and uses jpaTemplate. It's tagged as @Transactional, as well as all of the methods.

        I'd appreciate it very much if some you Spring gurus could point me to the right direction.

        TIA,
        Helgi.

        Comment


        • #5
          The solution

          By adding <tx:annotation-driven/> to the Spring context file (along with the name space and schema locations) and the cglib jar to the build path, things seems to work as expected.

          Regards,
          Helgi.

          Comment


          • #6
            I faced the same problem but then my DAO annotated with @Repository was altered to support extended persistence context and it worked !
            Code:
            @PersistenceContext(type = PersistenceContextType.EXTENDED)
            	private EntityManager entityManager;
            
            	public EntityManager getEntityManager() {
            		return entityManager;
            	}
            
            	public void setEntityManager(EntityManager entityManager) {
            		this.entityManager = entityManager;
            	}

            Code in application context :
            Code:
            	<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
            	
            	<!-- Enabling annotation driven configuration /-->
            	<context:annotation-config/>
            	<context:component-scan base-package="com.company.project.dao"/>  
            	<context:component-scan base-package="com.company.project.service"/>
            	
            	<!-- Annotation driven transaction management -->
            	<!-- Indicates Spring to put transactional advice on any class or method that has an @Transactional annotation on it -->
            	<tx:annotation-driven transaction-manager="transactionManager"/>
            	
            	
            	<!-- The JpaTransactionManager is responsible for creating EntityManagers opening transactions and binding them to the current thread context. -->
            	<!-- Now we just write our main DAO logic without having to worry about transactional semantics. -->
            	<bean class="org.springframework.orm.jpa.JpaTransactionManager">
            		<property name="entityManagerFactory" ref="entityManagerFactory" />
            	</bean>
            	
            	<!-- Spring container will act as a JPA container and inject an EnitityManager from your EntityManagerFactory -->
            	<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
            	
            	<!-- Spring's exception translation -->
            	<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
            
            
            <bean id="entityManagerFactory"
            		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            		<property name="dataSource" ref="myDataSource" />
            		<property name="persistenceUnitName" value="my-pu" />
            		<property name="jpaVendorAdapter">
            			<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter" />
            		</property>
            		<property name="loadTimeWeaver">
            			<bean class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver" />
            		</property>
            	</bean>

            Comment

            Working...
            X