环境:
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?
答案 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>