JBPM 5 - RESOURCE_LOCAL持久性

时间:2013-04-11 15:14:28

标签: drools jbpm

环境:

jbpm v5.4.0.Final, 流口水5.5.0.Final, 春天v3.0.6.RELEASE, 甲骨文, Hibernate EM v4.0.0.Final, JPA v2

我已将我的Web应用程序配置为使用带有RESOURCE_LOCAL事务的JBPM。

我面临三个问题:

1)表workiteminfo没有持久化

2)JPAWorkingMemoryDbLogger的日志未持久保存到数据库。

3)当人工任务完成时,即使在task -completion之后调用Session.getWorkItemManager().completeWorkItem,会话也不会执行实例中的其他节点。因此,没有创建新任务。

我已将persistence.xml配置为使用“RESOURCE_LOCAL”事务。 我已将DroolsSpringJPAManager配置为非JTA。

在创建会话环境时,是否应该显式创建命令范围的EntityManager?

1 个答案:

答案 0 :(得分:0)

以下是jBPM 5.4.0.Final:

的示例
package com.sample;

import java.util.List;

import javax.persistence.EntityManagerFactory;

import org.drools.KnowledgeBase;
import org.drools.SystemEventListenerFactory;
import org.drools.container.spring.beans.persistence.DroolsSpringJpaManager;
import org.drools.container.spring.beans.persistence.DroolsSpringTransactionManager;
import org.drools.impl.EnvironmentFactory;
import org.drools.persistence.PersistenceContextManager;
import org.drools.persistence.TransactionManager;
import org.drools.persistence.jpa.JPAKnowledgeService;
import org.drools.runtime.Environment;
import org.drools.runtime.EnvironmentName;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.process.ProcessInstance;
import org.jbpm.process.audit.JPAProcessInstanceDbLog;
import org.jbpm.process.audit.JPAWorkingMemoryDbLogger;
import org.jbpm.process.audit.ProcessInstanceLog;
import org.jbpm.process.workitem.wsht.SyncWSHumanTaskHandler;
import org.jbpm.task.TaskService;
import org.jbpm.task.identity.UserGroupCallback;
import org.jbpm.task.identity.UserGroupCallbackManager;
import org.jbpm.task.query.TaskSummary;
import org.jbpm.task.service.local.LocalTaskService;
import org.jbpm.task.service.persistence.TaskSessionSpringFactoryImpl;
import org.jbpm.test.JBPMHelper;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
import org.springframework.transaction.support.DefaultTransactionDefinition;

/**
 * This is a sample file to launch a process.
 */
public class TestSpringLocalEMF {

    public static final void main(String[] args) throws Throwable {
        JBPMHelper.startH2Server();

        UserGroupCallbackManager.getInstance().setCallback(new UserGroupCallback() {
            public boolean existsGroup(String arg0) {
                return true;
            }
            public boolean existsUser(String arg0) {
                return true;
            }
            public List<String> getGroupsForUser(String arg0,
                    List<String> arg1, List<String> arg2) {
                return arg2;
            }
        });

        ClassPathXmlApplicationContext context =
            new ClassPathXmlApplicationContext("spring-conf.xml");

        EntityManagerFactory emf = (EntityManagerFactory) context.getBean("jbpmEMF");

        Environment env = EnvironmentFactory.newEnvironment();  
        env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);       

        AbstractPlatformTransactionManager aptm = (AbstractPlatformTransactionManager) context.getBean( "jbpmTxManager" );      
        TransactionManager transactionManager = new DroolsSpringTransactionManager( aptm );
        env.set(EnvironmentName.TRANSACTION_MANAGER, transactionManager);

        PersistenceContextManager persistenceContextManager = new DroolsSpringJpaManager(env);
        env.set(EnvironmentName.PERSISTENCE_CONTEXT_MANAGER, persistenceContextManager);

        KnowledgeBase kbase = (KnowledgeBase) context.getBean("kbase");
        StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );
        new JPAWorkingMemoryDbLogger(ksession);

        org.jbpm.task.service.TaskService internalTaskService = new org.jbpm.task.service.TaskService();
        internalTaskService.setSystemEventListener(SystemEventListenerFactory.getSystemEventListener());
        TaskSessionSpringFactoryImpl springFactory = new TaskSessionSpringFactoryImpl();
        springFactory.setEntityManagerFactory(emf);     
        springFactory.setTaskService(internalTaskService);
        springFactory.setTransactionManager(transactionManager);
        springFactory.setUseJTA(true);
        springFactory.initialize();
        TaskService taskService = new LocalTaskService(internalTaskService);

        SyncWSHumanTaskHandler humanTaskHandler = new SyncWSHumanTaskHandler(taskService, ksession);
        humanTaskHandler.setLocal(true);
        humanTaskHandler.connect();
        ksession.getWorkItemManager().registerWorkItemHandler("Human Task", humanTaskHandler);

        ProcessInstance processInstance = ksession.startProcess("com.sample.bpmn.hello");

        System.out.println("Process started");

        List<TaskSummary> tasks = taskService.getTasksAssignedAsPotentialOwner("john", "en-UK");
        System.out.println("Found " + tasks.size() + " task(s) for user 'john'");
        if (tasks.size() != 1) {
            throw new IllegalArgumentException("Incorrect amount of tasks");
        }
        long taskId = tasks.get(0).getId();
        taskService.start(taskId, "john");
        taskService.complete(taskId, "john", null);

        tasks = taskService.getTasksAssignedAsPotentialOwner("mary", "en-UK");
        System.out.println("Found " + tasks.size() + " task(s) for user 'mary'");
        if (tasks.size() != 1) {
            throw new IllegalArgumentException("Incorrect amount of tasks");
        }
        taskId = tasks.get(0).getId();
        taskService.start(taskId, "mary");
        taskService.complete(taskId, "mary", null);

        processInstance = ksession.getProcessInstance(processInstance.getId());
        if (processInstance == null) {
            System.out.println("Process instance completed");
        }

        System.out.println("******************************************************************");

        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = aptm.getTransaction(def);

        processInstance = ksession.startProcess("com.sample.bpmn.hello");
        long processInstanceId = processInstance.getId();

        aptm.rollback(status);

        processInstance = ksession.getProcessInstance(processInstanceId);

        if (processInstance == null) {
            System.out.println("Process instance rolled back");
        } else {
            throw new IllegalArgumentException("Process instance not rolled back");
        }

        tasks = taskService.getTasksAssignedAsPotentialOwner("john", "en-UK");
        System.out.println("Found " + tasks.size() + " task(s) for user 'john'");
        if (tasks.size() != 0) {
            throw new IllegalArgumentException("Incorrect amount of tasks");
        }

        JPAProcessInstanceDbLog.setEnvironment(env);
        ProcessInstanceLog log = JPAProcessInstanceDbLog.findProcessInstance(processInstanceId);
        if (log != null) {
            throw new IllegalArgumentException("Log not rolled back");
        }

        System.exit(0);
    }

}

with 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.jbpm.persistence.jpa.local" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>jdbc/jbpm-ds</jta-data-source>

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

    <class>org.jbpm.persistence.processinstance.ProcessInstanceInfo</class>
    <class>org.drools.persistence.info.SessionInfo</class>
    <class>org.drools.persistence.info.WorkItemInfo</class>
    <class>org.drools.persistence.info.SessionInfo</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>

    <class>org.jbpm.task.Attachment</class>
    <class>org.jbpm.task.Content</class>
    <class>org.jbpm.task.BooleanExpression</class>
    <class>org.jbpm.task.Comment</class>
    <class>org.jbpm.task.Deadline</class>
    <class>org.jbpm.task.Comment</class>
    <class>org.jbpm.task.Deadline</class>
    <class>org.jbpm.task.Delegation</class>
    <class>org.jbpm.task.Escalation</class>
    <class>org.jbpm.task.Group</class>
    <class>org.jbpm.task.I18NText</class>
    <class>org.jbpm.task.Notification</class>
    <class>org.jbpm.task.EmailNotification</class>
    <class>org.jbpm.task.EmailNotificationHeader</class>
    <class>org.jbpm.task.PeopleAssignments</class>
    <class>org.jbpm.task.Reassignment</class>
    <class>org.jbpm.task.Status</class>
    <class>org.jbpm.task.Task</class>
    <class>org.jbpm.task.TaskData</class>
    <class>org.jbpm.task.SubTasksStrategy</class>
    <class>org.jbpm.task.OnParentAbortAllSubTasksEndStrategy</class>
    <class>org.jbpm.task.OnAllSubTasksEndParentEndStrategy</class>
    <class>org.jbpm.task.User</class>

    <properties>
      <property name="hibernate.max_fetch_depth" value="3"/>
      <property name="hibernate.hbm2ddl.auto" value="create" />
      <property name="hibernate.show_sql" value="true" />   
      <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
    </properties>

  </persistence-unit>

</persistence>

和spring-conf.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:jbpm="http://drools.org/schema/drools-spring"       
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                           http://drools.org/schema/drools-spring org/drools/container/spring/drools-spring-1.5.0.xsd">

  <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="org.h2.Driver"/>
    <property name="url" value="jdbc:h2:tcp://localhost/~/jbpm-db"/>
    <property name="username" value="sa"/>
    <property name="password" value=""/>
  </bean>

  <bean id="jbpmEMF" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="persistenceUnitName" value="org.jbpm.persistence.jpa.local"/>
  </bean>

  <bean id="jbpmTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="jbpmEMF"/>
    <property name="nestedTransactionAllowed" value="false"/>
  </bean>

  <jbpm:kbase id="kbase">
    <jbpm:resources>
      <jbpm:resource type="BPMN2" source="classpath:sample.bpmn"/>
    </jbpm:resources>
  </jbpm:kbase>

</beans>

和sample.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.hello" name="Hello World" >

    <!-- nodes -->
    <startEvent id="_1" name="Start" />
    <endEvent id="_3" name="End" >
        <terminateEventDefinition/>
    </endEvent>
    <userTask id="_4" name="Task 1" >
      <ioSpecification>
        <dataInput id="_4_CommentInput" name="Comment" />
        <dataInput id="_4_SkippableInput" name="Skippable" />
        <dataInput id="_4_TaskNameInput" name="TaskName" />
        <dataInput id="_4_ContentInput" name="Content" />
        <dataInput id="_4_GroupIdInput" name="GroupId" />
        <dataInput id="_4_PriorityInput" name="Priority" />
        <inputSet>
          <dataInputRefs>_4_CommentInput</dataInputRefs>
          <dataInputRefs>_4_SkippableInput</dataInputRefs>
          <dataInputRefs>_4_TaskNameInput</dataInputRefs>
          <dataInputRefs>_4_ContentInput</dataInputRefs>
          <dataInputRefs>_4_GroupIdInput</dataInputRefs>
          <dataInputRefs>_4_PriorityInput</dataInputRefs>
        </inputSet>
        <outputSet>
        </outputSet>
      </ioSpecification>
      <dataInputAssociation>
        <targetRef>_4_CommentInput</targetRef>
        <assignment>
          <from xsi:type="tFormalExpression"></from>
          <to xsi:type="tFormalExpression">_4_CommentInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_4_SkippableInput</targetRef>
        <assignment>
          <from xsi:type="tFormalExpression">false</from>
          <to xsi:type="tFormalExpression">_4_SkippableInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_4_TaskNameInput</targetRef>
        <assignment>
          <from xsi:type="tFormalExpression">Task1</from>
          <to xsi:type="tFormalExpression">_4_TaskNameInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_4_ContentInput</targetRef>
        <assignment>
          <from xsi:type="tFormalExpression"></from>
          <to xsi:type="tFormalExpression">_4_ContentInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_4_GroupIdInput</targetRef>
        <assignment>
          <from xsi:type="tFormalExpression"></from>
          <to xsi:type="tFormalExpression">_4_GroupIdInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_4_PriorityInput</targetRef>
        <assignment>
          <from xsi:type="tFormalExpression"></from>
          <to xsi:type="tFormalExpression">_4_PriorityInput</to>
        </assignment>
      </dataInputAssociation>
      <potentialOwner>
        <resourceAssignmentExpression>
          <formalExpression>john</formalExpression>
        </resourceAssignmentExpression>
      </potentialOwner>
    </userTask>
    <userTask id="_5" name="Task 2" >
      <ioSpecification>
        <dataInput id="_5_CommentInput" name="Comment" />
        <dataInput id="_5_SkippableInput" name="Skippable" />
        <dataInput id="_5_TaskNameInput" name="TaskName" />
        <dataInput id="_5_ContentInput" name="Content" />
        <dataInput id="_5_GroupIdInput" name="GroupId" />
        <dataInput id="_5_PriorityInput" name="Priority" />
        <inputSet>
          <dataInputRefs>_5_CommentInput</dataInputRefs>
          <dataInputRefs>_5_SkippableInput</dataInputRefs>
          <dataInputRefs>_5_TaskNameInput</dataInputRefs>
          <dataInputRefs>_5_ContentInput</dataInputRefs>
          <dataInputRefs>_5_GroupIdInput</dataInputRefs>
          <dataInputRefs>_5_PriorityInput</dataInputRefs>
        </inputSet>
        <outputSet>
        </outputSet>
      </ioSpecification>
      <dataInputAssociation>
        <targetRef>_5_CommentInput</targetRef>
        <assignment>
          <from xsi:type="tFormalExpression"></from>
          <to xsi:type="tFormalExpression">_5_CommentInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_5_SkippableInput</targetRef>
        <assignment>
          <from xsi:type="tFormalExpression">false</from>
          <to xsi:type="tFormalExpression">_5_SkippableInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_5_TaskNameInput</targetRef>
        <assignment>
          <from xsi:type="tFormalExpression">Task2</from>
          <to xsi:type="tFormalExpression">_5_TaskNameInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_5_ContentInput</targetRef>
        <assignment>
          <from xsi:type="tFormalExpression"></from>
          <to xsi:type="tFormalExpression">_5_ContentInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_5_GroupIdInput</targetRef>
        <assignment>
          <from xsi:type="tFormalExpression"></from>
          <to xsi:type="tFormalExpression">_5_GroupIdInput</to>
        </assignment>
      </dataInputAssociation>
      <dataInputAssociation>
        <targetRef>_5_PriorityInput</targetRef>
        <assignment>
          <from xsi:type="tFormalExpression"></from>
          <to xsi:type="tFormalExpression">_5_PriorityInput</to>
        </assignment>
      </dataInputAssociation>
      <potentialOwner>
        <resourceAssignmentExpression>
          <formalExpression>mary</formalExpression>
        </resourceAssignmentExpression>
      </potentialOwner>
    </userTask>

    <!-- connections -->
    <sequenceFlow id="_5-_3" sourceRef="_5" targetRef="_3" />
    <sequenceFlow id="_1-_4" sourceRef="_1" targetRef="_4" />
    <sequenceFlow id="_4-_5" sourceRef="_4" targetRef="_5" />

  </process>

  <bpmndi:BPMNDiagram>
    <bpmndi:BPMNPlane bpmnElement="com.sample.bpmn.hello" >
      <bpmndi:BPMNShape bpmnElement="_1" >
        <dc:Bounds x="16" y="16" width="48" height="48" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_3" >
        <dc:Bounds x="360" y="16" width="48" height="48" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_4" >
        <dc:Bounds x="96" y="16" width="100" height="48" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_5" >
        <dc:Bounds x="228" y="16" width="100" height="48" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="_5-_3" >
        <di:waypoint x="278" y="40" />
        <di:waypoint x="384" y="40" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_1-_4" >
        <di:waypoint x="40" y="40" />
        <di:waypoint x="146" y="40" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_4-_5" >
        <di:waypoint x="146" y="40" />
        <di:waypoint x="278" y="40" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>

</definitions>