如上篇(使用 BPMN2 Modeler 创建 jBPM 6 流程)中所示,我们演示通过 jBPM 6 eclipse 插件如何 step by step 的创建 BPMN2 流程,我们最终创建的流程如下:
我们将如上流程称作为 jBPM Rewards流程,即请求者提出申请一个奖励,流程开始,申请奖励的请求首先被PM允许,接着被HR允许,流程结束,请求者得到奖励。从流程的角度去说,rewards流程包括6个节点:
本示例主要内容可以概括为:
我们通过如下几步来运行jBPM 6 rewards示例。
rewards.bpmn(使用 BPMN2 Modeler 创建 jBPM 6 流程中设计)位于classpath中org/jbpm/demo目录下。
kmodule.xml 位于classpath 中 META-INF下,内容如下所示:
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> <kbase name="kbase" packages="org.jbpm.demo" /> </kmodule>
package org.jbpm.demo.rewards; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import org.jbpm.test.JBPMHelper; import org.kie.api.KieBase; import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; import org.kie.api.runtime.manager.RuntimeEngine; import org.kie.api.runtime.manager.RuntimeEnvironmentBuilder; import org.kie.api.runtime.manager.RuntimeManager; import org.kie.api.runtime.manager.RuntimeManagerFactory; import org.kie.api.task.TaskService; import org.kie.api.task.model.TaskSummary; public class ProcessMain { public static void main(String[] args) { KieServices ks = KieServices.Factory.get(); KieContainer kContainer = ks.getKieClasspathContainer(); KieBase kbase = kContainer.getKieBase("kbase"); RuntimeManager manager = createRuntimeManager(kbase); RuntimeEngine engine = manager.getRuntimeEngine(null); KieSession ksession = engine.getKieSession(); TaskService taskService = engine.getTaskService(); Map<String, Object> params = new HashMap<String, Object>(); params.put("recipient", "kylin"); ksession.startProcess("org.jbpm.demo.rewards", params); // let john execute Task 1 List<TaskSummary> list = taskService.getTasksAssignedAsPotentialOwner("john", "en-UK"); TaskSummary task = list.get(0); taskService.start(task.getId(), "john"); taskService.complete(task.getId(), "john", null); // let mary execute Task 2 list = taskService.getTasksAssignedAsPotentialOwner("mary", "en-UK"); task = list.get(0); taskService.start(task.getId(), "mary"); taskService.complete(task.getId(), "mary", null); manager.disposeRuntimeEngine(engine); System.exit(0); } private static RuntimeManager createRuntimeManager(KieBase kbase) { JBPMHelper.startH2Server(); JBPMHelper.setupDataSource(); EntityManagerFactory emf = Persistence.createEntityManagerFactory("org.jbpm.persistence.jpa"); RuntimeEnvironmentBuilder builder = RuntimeEnvironmentBuilder.Factory.get().newDefaultBuilder().entityManagerFactory(emf).knowledgeBase(kbase); return RuntimeManagerFactory.Factory.get().newSingletonRuntimeManager(builder.get(), "com.sample:example:1.0"); } }
运行ProcessMain会有如下输出:
process 33 started by kylin john approved process 33 mary approved process 33 process 33 finished
数据存储(JPA)
如上运行过程中我们使用到H2数据库存储运行过程中的数据,jBPM 6通过JPA/hibernate来操作数据库,RuntimeEnvironmentBuilder中传入创建的EntityManagerFactory(org.jbpm.persistence.jpa),我们可以在jbpm-test-6.0.0.Final.jar中找到JPA persist-unit的定义,persistence.xml位于jbpm-test-6.0.0.Final.jar/META-INF下,内容如下:
<persistence version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_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" transaction-type="JTA"> <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/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.jbpm.process.audit.ProcessInstanceLog</class> <class>org.jbpm.process.audit.NodeInstanceLog</class> <class>org.jbpm.process.audit.VariableInstanceLog</class> <class>org.jbpm.persistence.correlation.CorrelationKeyInfo</class> <class>org.jbpm.persistence.correlation.CorrelationPropertyInfo</class> <!-- manager --> <class>org.jbpm.runtime.manager.impl.jpa.ContextMappingInfo</class> <class>org.jbpm.services.task.impl.model.AttachmentImpl</class> <class>org.jbpm.services.task.impl.model.ContentImpl</class> <class>org.jbpm.services.task.impl.model.BooleanExpressionImpl</class> <class>org.jbpm.services.task.impl.model.CommentImpl</class> <class>org.jbpm.services.task.impl.model.DeadlineImpl</class> <class>org.jbpm.services.task.impl.model.CommentImpl</class> <class>org.jbpm.services.task.impl.model.DeadlineImpl</class> <class>org.jbpm.services.task.impl.model.DelegationImpl</class> <class>org.jbpm.services.task.impl.model.EscalationImpl</class> <class>org.jbpm.services.task.impl.model.GroupImpl</class> <class>org.jbpm.services.task.impl.model.I18NTextImpl</class> <class>org.jbpm.services.task.impl.model.NotificationImpl</class> <class>org.jbpm.services.task.impl.model.EmailNotificationImpl</class> <class>org.jbpm.services.task.impl.model.EmailNotificationHeaderImpl</class> <class>org.jbpm.services.task.impl.model.PeopleAssignmentsImpl</class> <class>org.jbpm.services.task.impl.model.ReassignmentImpl</class> <class>org.jbpm.services.task.impl.model.TaskImpl</class> <class>org.jbpm.services.task.impl.model.TaskDataImpl</class> <class>org.jbpm.services.task.impl.model.UserImpl</class> <!--BAM for task service --> <class>org.jbpm.services.task.impl.model.BAMTaskSummaryImpl</class> <properties> <property name="hibernate.max_fetch_depth" value="3"/> <property name="hibernate.hbm2ddl.auto" value="update" /> <property name="hibernate.show_sql" value="false" /> <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/> <!-- BZ 841786: AS7/EAP 6/Hib 4 uses new (sequence) generators which seem to cause problems --> <property name="hibernate.id.new_generator_mappings" value="false" /> <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.BitronixJtaPlatform" /> </properties> </persistence-unit> </persistence>
本示例还演示了如何使用 Maven 快速构建 jBPM 6 测试工程,创建 jBPM 6 测试工程只需要依赖一个依赖包:
<dependency> <groupId>org.jbpm</groupId> <artifactId>jbpm-test</artifactId> <version>${jbpm.version}</version> </dependency>
package org.jbpm.demo.rewards; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jbpm.test.JbpmJUnitBaseTestCase; import org.junit.Test; import org.kie.api.runtime.KieSession; import org.kie.api.runtime.manager.RuntimeEngine; import org.kie.api.runtime.manager.RuntimeManager; import org.kie.api.task.TaskService; import org.kie.api.task.model.TaskSummary; public class ProcessTest extends JbpmJUnitBaseTestCase{ public ProcessTest() { super(true, true); } @Test public void testRewardsProcess() { RuntimeManager manager = createRuntimeManager("org/jbpm/demo/rewards.bpmn"); RuntimeEngine engine = manager.getRuntimeEngine(null); KieSession ksession = engine.getKieSession(); TaskService taskService = engine.getTaskService(); Map<String, Object> params = new HashMap<String, Object>(); params.put("recipient", "kylin"); ksession.startProcess("org.jbpm.demo.rewards", params); // let john execute Task 1 List<TaskSummary> list = taskService.getTasksAssignedAsPotentialOwner("john", "en-UK"); TaskSummary task = list.get(0); taskService.start(task.getId(), "john"); taskService.complete(task.getId(), "john", null); // let mary execute Task 2 list = taskService.getTasksAssignedAsPotentialOwner("mary", "en-UK"); task = list.get(0); taskService.start(task.getId(), "mary"); taskService.complete(task.getId(), "mary", null); manager.disposeRuntimeEngine(engine); } }
运行ProcessTest 同样输出:
process 1 started by kylin john approved process 1 mary approved process 1 process 1 finished