1 Reply Latest reply on Jul 24, 2012 6:08 AM by swiderski.maciej

    "Entity manager is closed" when using spring defined sessions, and async work item handlers

    fosoriog

      I'm receiving the following stacktrace when trying to complete a workitem:

       

      Exception in thread "Thread-1" java.lang.IllegalStateException: EntityManager is closed

          at org.hibernate.ejb.EntityManagerImpl.getSession(EntityManagerImpl.java:66)

          at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:182)

          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

          at java.lang.reflect.Method.invoke(Method.java:597)

          at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)

          at $Proxy17.find(Unknown Source)

          at org.drools.persistence.jpa.JpaPersistenceContext.findWorkItemInfo(JpaPersistenceContext.java:41)

          at org.drools.persistence.jpa.processinstance.JPAWorkItemManager.completeWorkItem(JPAWorkItemManager.java:110)

          at com.sample.test.AsyncWorkItemHandler$1.run(AsyncWorkItemHandler.java:21)

          at java.lang.Thread.run(Thread.java:662)

       

      I've created a minimal workflow and code that reproduces this problem. Here is my session definition:

       

      session.xml:

      <?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:drools-spring="http://drools.org/schema/drools-spring"

          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

              http://drools.org/schema/drools-spring http://drools.org/schema/drools-spring.xsd">

       

       

      <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

            <property name="dataSource" ref="dataSource"/>

            <property name="persistenceUnitName" value="org.drools.persistence.jpa.local"/>

      </bean>

       

      <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">

            <property name="entityManagerFactory" ref="entityManagerFactory"/>

      </bean>

       

      <drools-spring:grid-node id="node1"/>

       

      <drools-spring:kbase id="kbase" node="node1">

         <drools-spring:resources>

           <drools-spring:resource type="BPMN2" source="classpath:test.bpmn"/>

         </drools-spring:resources>

      </drools-spring:kbase>

       

       

      <drools-spring:ksession id="ksession" type="stateful" kbase="kbase" node="node1">

            <drools-spring:configuration>

              <drools-spring:jpa-persistence>

                <drools-spring:transaction-manager ref="txManager"/>

                <drools-spring:entity-manager-factory ref="entityManagerFactory"/>

              </drools-spring:jpa-persistence>

              <drools-spring:work-item-handlers>

                  <drools-spring:work-item-handler name="JavaServiceNode" ref="asyncWorkItemHandler"/>

              </drools-spring:work-item-handlers>

            </drools-spring:configuration>

      </drools-spring:ksession>

       

      <bean id="asyncWorkItemHandler" class="com.sample.test.AsyncWorkItemHandler"/>

       

         <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

          <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>

          <property name="url" value="jdbc:oracle:thin:@[...DBURL...]"/>

          <property name="username" value="[username]"/>

          <property name="password" value="[password]"/>

        </bean>

       

       

      </beans>

      Persistence.xml

      <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

      <persistence version="1.0"

        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd

           http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"

        xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xmlns="http://java.sun.com/xml/ns/persistence">

       

        <persistence-unit name="org.drools.persistence.jpa.local" transaction-type="RESOURCE_LOCAL">

          <provider>org.hibernate.ejb.HibernatePersistence</provider>

          <jta-data-source>jdbc/my-ds</jta-data-source>

          <mapping-file>META-INF/JBPMorm.xml</mapping-file>

          <mapping-file>META-INF/ProcessInstanceInfo.hbm.xml</mapping-file>

       

          <class>org.drools.persistence.info.SessionInfo</class>

          <class>org.jbpm.persistence.processinstance.ProcessInstanceInfo</class>

          <class>org.drools.persistence.info.WorkItemInfo</class>

       

          <class>org.jbpm.process.audit.ProcessInstanceLog</class>

          <class>org.jbpm.process.audit.NodeInstanceLog</class>

          <class>org.jbpm.process.audit.VariableInstanceLog</class>

       

          <properties>

                <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>

                <property name="hibernate.max_fetch_depth" value="3"/>

                <property name="hibernate.hbm2ddl.auto" value="validate" />

                <property name="hibernate.show_sql" value="true" />

                <property name="hibernate.connection.datasource" value="java:comp/env/my-ds"/>

          </properties>

       

        </persistence-unit>

      </persistence>

       

      test.bpmn:

      <?xml version="1.0" encoding="UTF-8"?>

      <definitions id="Definition"

                   targetNamespace="http://www.jboss.org/drools"

                   typeLanguage="http://www.java.com/javaTypes"

                   expressionLanguage="http://www.mvel.org/2.0"

                   xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"

                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                   xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"

                   xmlns:g="http://www.jboss.org/drools/flow/gpd"

                   xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"

                   xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"

                   xmlns:di="http://www.omg.org/spec/DD/20100524/DI"

                   xmlns:tns="http://www.jboss.org/drools">

       

        <process processType="Private" isExecutable="true" id="com.sample.bpmn" name="Sample Process" tns:packageName="defaultPackage" >

       

          <!-- nodes -->

          <startEvent id="_1" name="StartProcess" />

          <endEvent id="_2" name="End" >

              <terminateEventDefinition/>

          </endEvent>

          <task id="_3" name="Java Service Node" tns:taskName="JavaServiceNode" >

            <ioSpecification>

              <inputSet>

              </inputSet>

              <outputSet>

              </outputSet>

            </ioSpecification>

          </task>

       

          <!-- connections -->

          <sequenceFlow id="_3-_2" sourceRef="_3" targetRef="_2" />

          <sequenceFlow id="_1-_3" sourceRef="_1" targetRef="_3" />

       

        </process>

       

      </definitions>

       

       

      AsyncWorkItemHandler.java:

      package com.sample.test;

       

      import java.util.HashMap;

      import java.util.Map;

       

      import org.drools.runtime.process.WorkItem;

      import org.drools.runtime.process.WorkItemHandler;

      import org.drools.runtime.process.WorkItemManager;

       

      public class AsyncWorkItemHandler implements WorkItemHandler

      {

       

          public void executeWorkItem(final WorkItem workItem, final WorkItemManager manager)

          {

              new Thread(new Runnable() {

                  public void run()

                  {

                      Object result = "result from an invoked service here...";

                      Map<String, Object> results = new HashMap<String, Object>();

                      results.put("result", result);

                      manager.completeWorkItem(workItem.getId(), results);  //HERE THE EXCEPTION IS THROWN

                      return;

                  }

              }).start();

       

          }

       

          public void abortWorkItem(WorkItem workItem, WorkItemManager manager)

          {

          }

      }

       

       

      TestAsyncHandler.java:

      package com.sample.test;

      import org.drools.runtime.StatefulKnowledgeSession;

      import org.springframework.context.support.ClassPathXmlApplicationContext;

       

      public class TestAsyncHandler

      {

          public static void main(String[] args)

          {

              ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("session.xml");

              StatefulKnowledgeSession ksession = (StatefulKnowledgeSession) context.getBean("ksession");

              ksession.startProcess("com.sample.bpmn");

              System.out.println("done");

          }

      }

       

       

      The mentioned exception is thrown on the manager.completeWorkItem .. line because the entity manager is closed by the time the ksession.startProcess("com.sample.bpmn") line returns. Somehow they are sharing the same entity manager.

       

      I'm obviously missing something here, but I'm at loss as to what it is. I followed the jbpm guide for the spring integration.

       

      Any help is much appreciated.

       

      Thanks.