10 Replies Latest reply on Dec 8, 2014 8:18 AM by vishal.m116

    Problem in JPAWorkItemManager when completing a task

    juan.gago

      Hi all!

      I'm trying to integrate jBPM 5.2 (workflow with human tasks) in a Spring application with JPA. I am using CommandBasedWSHumanTaskHandler for the persistence of tasks generated in the workflow. Everything works fine except when running the response handler to complete a task (GetCompletedTaskResponseHandler). The applicaton uses the JPAWorkItemManager, but when it tries to complete the task to continue with the flow, error occurs because the manager uses the context stored in the environment of the session (StatefulKnowledgeSessionImpl) to retrieve the WorItemInfo. The problem is because the context has a connection to the EntityManager closed.

      What could be the problem?, Will I have misconfigured the session?, What class should be responsible for opening the connection to the EntityManager and store the context in the session environment for JPAWorkItemManager use?

       

      Thanks!

        • 1. Re: Problem in JPAWorkItemManager when completing a task
          salaboy21

          Hi Juan,

          Can you share how you are configuring persistence? Are you using JPAKnowledgeService to create your session?

          Are you calling the dispose method each time that you end up interacting with the session?

          Do you have the session loaded when you finish the human task?

          Cheers

          • 2. Re: Problem in JPAWorkItemManager when completing a task
            salaboy21

            Hi Juan,

            Can you share how you are configuring persistence? Are you using JPAKnowledgeService to create your session?

            Are you calling the dispose method each time that you end up interacting with the session?

            Do you have the session loaded when you finish the human task?

            Cheers

            • 3. Re: Problem in JPAWorkItemManager when completing a task
              salaboy21

              Hi Juan,

              Can you share how you are configuring persistence? Are you using JPAKnowledgeService to create your session?

              Are you calling the dispose method each time that you end up interacting with the session?

              Do you have the session loaded when you finish the human task?

              Cheers

              • 4. Re: Problem in JPAWorkItemManager when completing a task
                gardellajp

                Hi,

                 

                For complete a Task, you must have the session open and the client that you are using must register listener to update the session (if you are using TaskClient). See the code inside CommandBasedWSHumanTaskHandler.connect(). Remember (is not in official doc) that is not automatically the refresh of the session when you call taskClient.complete(...), you must explicity define a listener that must update the session state.

                 

                You can extend CommandBasedWSHumanTaskHandler and make a setter of TaskClient or look this class to make your solution. I did a simple helper clasess to manage this.

                 

                Juan

                • 5. Re: Problem in JPAWorkItemManager when completing a task
                  juan.gago

                  Thanks for the response

                   

                   

                  I am using JPAKnowledgeService, initialized from Spring application context configuration file:

                            <jbpm:kbase id="kbase">

                                      <jbpm:resources>

                                                <jbpm:resource type="BPMN2" source="classpath:workflows/Test.bpmn" />

                                      </jbpm:resources>

                            </jbpm:kbase>

                            <jbpm:ksession id="ksession" type="stateful" kbase="kbase">

                                      <jbpm:configuration>

                                                <jbpm:jpa-persistence>

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

                                                          <jbpm:transaction-manager ref="transactionManager"/>

                                                </jbpm:jpa-persistence>

                                      </jbpm:configuration>

                            </jbpm:ksession>

                   

                   

                  CommandBasedWSHumanTaskHandler is configured to execute connect method at application startup.

                  And for completing a task, the code just execute the task client method:

                            BlockingTaskOperationResponseHandler completeResponseHandler = new BlockingTaskOperationResponseHandler();

                            getTaskClient().complete(taskId, userId, null, completeResponseHandler);

                            completeResponseHandler.waitTillDone(getClientMaxWaitTime());

                   

                   

                  The session is loaded, because I previously can create process instances, and the task client can change task status to Completed.

                   

                   

                  Should I do something more? What listener must I declare?

                  The CommandBasedWSHumanTaskHandler.connect method works fine, but when TaskCompletedHandler executes its routine (using JPAWorkItemManager.completeWorkItem), the PersistenceContext stored in the session environment has a reference to a closed EntityManager.

                  • 6. Re: Problem in JPAWorkItemManager when completing a task
                    gardellajp

                    I spent two days try complete a task and update process state, and the solution I've found was register listener to the task client. Suppose you are using a TaskClient c. If you use c to complete the task, you must configure c like are configure in CommandBasedWSHumanTaskHandler.connect().

                     

                    Juan

                    • 7. Re: Problem in JPAWorkItemManager when completing a task
                      juan.gago

                      I am using org.jbpm.task.service.TaskClient, and it works fine. The TaskServer receives the message and set task status to completed (updates database), but the problem occurs in org.jbpm.process.workitem.wsht.CommandBasedWSHumanTaskHandler.GetCompletedTaskResponseHandler.execute(Task task) method. It tries to execute session.getWorkItemManager().completeWorkItem(workItemId, results), but fails because the EntityManager connection is closed.

                       

                      Are you implementing a TaskClient? I don't understand how you can open the EntityManager connection in the TaskClient.

                       

                      Thanks for your answer

                      • 8. Re: Problem in JPAWorkItemManager when completing a task
                        juan.gago

                        Solved!

                         

                        Thanks for answers. I finally found a Spring 3 JPA JBPM 5.2 correct configuration. Here is (I hope it helps someone):

                         

                        <!-- First: declare JBPM JPA Session with a process definition -->

                          <jbpm:kbase id="kbase">

                            <jbpm:resources>

                              <jbpm:resource type="BPMN2" source="classpath:workflows/Test.bpmn" />

                            </jbpm:resources>

                          </jbpm:kbase>

                          <jbpm:ksession id="ksession" type="stateful" kbase="kbase">

                            <jbpm:configuration>

                              <jbpm:jpa-persistence>

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

                                <jbpm:transaction-manager ref="transactionManager"/>

                              </jbpm:jpa-persistence>

                            </jbpm:configuration>

                          </jbpm:ksession>

                         

                          <!-- Declare a TaskServer -->

                          <bean class="org.jbpm.task.service.TaskService" id="taskService">

                            <constructor-arg ref="entityManagerFactory"/>

                            <constructor-arg>

                              <bean class="org.drools.SystemEventListenerFactory" factory-method="getSystemEventListener"/>

                            </constructor-arg>

                          </bean>

                          <bean class="org.jbpm.task.service.mina.MinaTaskServer" id="taskServer">

                            <constructor-arg ref="taskService"/>

                            <constructor-arg><value>${jbpm.task.server.port}</value></constructor-arg>

                          </bean>

                          <!-- And start TaskServer on the configured port -->

                          <bean class="java.lang.Thread" id="taskServerThread" init-method="start">

                            <constructor-arg ref="taskServer"/>

                          </bean>

                         

                          <!-- Declare a TaskClient -->

                          <bean class="org.jbpm.task.service.mina.MinaTaskClientConnector" id="taskClientConnector">

                            <constructor-arg value="taskClient"/>

                            <constructor-arg>

                              <bean class="org.jbpm.task.service.mina.MinaTaskClientHandler">

                                <constructor-arg>

                                  <bean class="org.drools.SystemEventListenerFactory" factory-method="getSystemEventListener"/>

                                </constructor-arg>

                              </bean>

                            </constructor-arg>

                          </bean>

                          <bean class="org.jbpm.task.service.TaskClient" id="taskClient">

                            <constructor-arg ref="taskClientConnector"/>

                          </bean>

                         

                          <!-- Declare a HumanTaskHandler. It uses previously created TaskClient -->

                          <bean class="org.jbpm.task.service.AsyncTaskServiceWrapper" id="humanTaskClient">

                            <constructor-arg ref="taskClient"/>

                          </bean>

                          <bean class="org.jbpm.process.workitem.wsht.SyncWSHumanTaskHandler" id="humanTaskHandler">

                            <constructor-arg ref="humanTaskClient"/>

                            <constructor-arg ref="ksession"/>

                          </bean>

                          <!-- Configure its connection to the local server -->

                          <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="humanTaskHandler" id="setConnection">

                            <property name="targetObject" ref="humanTaskHandler"/>

                            <property name="targetMethod" value="setConnection"/>

                            <property name="arguments">

                              <list>

                                <value>${jbpm.task.client.address}</value>

                                <value>${jbpm.task.client.port}</value>

                              </list>

                            </property>

                          </bean>

                          <!-- And connect HumanTaskHandler (implicit TaskClient connection) -->

                          <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="setConnection">

                            <property name="targetObject" ref="humanTaskHandler"/>

                            <property name="targetMethod" value="connect"/>

                          </bean>

                         

                          <!-- Finnaly, register HumanTaskHandler in the session -->

                          <bean factory-bean="ksession" factory-method="getWorkItemManager" id="workItemManager"/>

                          <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">

                            <property name="targetObject" ref="workItemManager"/>

                            <property name="targetMethod" value="registerWorkItemHandler"/>

                            <property name="arguments">

                              <list>

                                <value>Human Task</value>

                                <ref bean="humanTaskHandler"/>

                              </list>

                            </property>

                          </bean>

                         

                        This way, I can configure JBPM with Tasks (server and client) without any lines of JAVA code, using Spring.

                        • 9. Re: Problem in JPAWorkItemManager when completing a task
                          gardellajp

                          Wow! Thanks for sharing it.

                          • 10. Re: Problem in JPAWorkItemManager when completing a task
                            vishal.m116

                            Hi Juan,

                             

                            I am also implementing jBPM 5.2 with Spring. Your reply really helped me configure my jBPM. Can you please share a sample project or code for executing the Human task?

                            It would be really helpful for newbies like me.