jBPM-4.4:主流程(process)与子流程(sub-process)之间交换数据

现在假设存在这样一个流程:

首先需要进行复杂的鉴权,而且可能随着需求的变化而变化,这导致鉴权的流程也是时刻可能变化的。而只有当鉴权成功以后,才能执行实际的交易操作,例如向外部系统发送请求报文获取某些交易的数据。

这时,可以考虑将鉴权流程独立做成一个子流程,然后将其嵌入到主流程中去,适应局部流程变化而无需修改全局流程的问题,在子流程与主流程之间实际要做的就是约定数据的交换协议,即确定数据在子流程与主流程之间的流入与流出。

下面通过一个实际例子来说明并实践。

首先,定义主流程。

主流程包含鉴权的子流程,鉴权通过之后,收集鉴权过程中获取到的交易必需的数据,组装请求报文,流程定义如图所示:

jBPM-4.4:主流程(process)与子流程(sub-process)之间交换数据_第1张图片

对应的流程定义文件main-process.jpdl.xml,如下所示:

 <?xml version="1.0" encoding="UTF-8"?> <process name="MainProcess" xmlns="http://jbpm.org/4.4/jpdl"> <start g="347,93,48,48"> <transition g="-123,-22" name="to SubCheckProcess" to="SubCheckProcess"/> </start> <sub-process g="297,173,149,40" name="SubCheckProcess" sub-process-key="SubCheckProcess"> <parameter-in subvar="myRequest" var="myRequest"/> <parameter-out subvar="myRequest" var="myRequest"/> <transition g="-114,-22" name="to ExternalRequest" to="ExternalRequest"/> </sub-process> <end g="347,329,48,48" name="end"/> <custom class="com.umpay.workflow.jbpm.handler.ExternalRequestHandler" g="306,245,131,52" name="ExternalRequest"> <transition g="-43,-22" name="to end" to="end"/> </custom> </process>

上面,sub-process-key="SubCheckProcess"表示一个嵌入主流程中的鉴权子流程。通过流程定义文件内容,可以看到,在主流程与子流程之间交换数据,是通过变量myRequest来实现的:

<sub-process g="297,173,149,40" name="SubCheckProcess" sub-process-key="SubCheckProcess"> <parameter-in subvar="myRequest" var="myRequest"/> <parameter-out subvar="myRequest" var="myRequest"/> <transition g="-114,-22" name="to ExternalRequest" to="ExternalRequest"/>

<parameter-in>元素表示从主流程MainProcess中流入到子流程SubCheckProcess中变量为myRequest,而var="myRequest"表示在主流程中变量名称,而subvar="myRequest"表示在子流程中可以通过获取到myRequest变量从而得到数据。同理,<parameter-out>元素表示从子流程SubCheckProcess中流出到MainProcess中,将数据又传回主流程中,继续后续流程的操作。

另外,主流程在执行完子流程后,又执行了ExternalRequest结点,对应的处理类为com.umpay.workflow.jbpm.handler.ExternalRequestHandler,如下所示:

package com.umpay.workflow.jbpm.handler; import java.util.Map; import org.jbpm.api.activity.ActivityBehaviour; import org.jbpm.api.activity.ActivityExecution; public class ExternalRequestHandler implements ActivityBehaviour { @Override public void execute(ActivityExecution execution) throws Exception { Map<String, Object> myRequest = (Map<String, Object>)execution.getVariable("myRequest"); System.out.println("Main process variables: " + myRequest); } }

然后,实现子流程。

子流程定义,如图所示:

jBPM-4.4:主流程(process)与子流程(sub-process)之间交换数据_第2张图片

对应的流程定义文件sub-check-process.jpdl.xml,内容如下所示:

<?xml version="1.0" encoding="UTF-8"?> <process name="SubCheckProcess" xmlns="http://jbpm.org/4.4/jpdl"> <start g="332,2,48,52"> <transition g="-112,-22" name="to CheckCustomer" to="CheckCustomer"/> </start> <custom class="com.umpay.workflow.jbpm.handler.CheckCustomerHandler" g="302,86,108,52" name="CheckCustomer"> <transition g="-52,-22" name="to fork1" to="fork1"/> </custom> <custom class="com.umpay.workflow.jbpm.handler.CheckMerHandler" g="186,250,92,52" name="CheckMer"> <transition g="-58,-8" name="to join1" to="join1"/> </custom> <custom class="com.umpay.workflow.jbpm.handler.CheckBankHandler" g="310,250,92,52" name="CheckBank"> <transition name="to join1" to="join1" g="0,-13"/> </custom> <custom class="com.umpay.workflow.jbpm.handler.CheckGoodsHandler" g="434,250,92,52" name="CheckGoods"> <transition name="to join1" to="join1" g="21,-4"/> </custom> <custom class="com.umpay.workflow.jbpm.handler.CheckMerBankHandler" g="295,414,122,52" name="CheckMerBank"> <transition name="to CheckGoodsBank" to="CheckGoodsBank" g="-124,-22"/> </custom> <custom class="com.umpay.workflow.jbpm.handler.CheckGoodsBankHandler" g="289,498,134,52" name="CheckGoodsBank"> <transition name="to end1" to="end1" g="-50,-22"/> </custom> <fork g="332,170,48,48" name="fork1"> <transition g="-80,-22" name="to CheckMer" to="CheckMer"/> <transition g="-46,-13" name="to CheckBank" to="CheckBank"/> <transition g="1,-21" name="to CheckGoods" to="CheckGoods"/> </fork> <join g="332,334,48,48" name="join1"> <transition name="to CheckMerBank" to="CheckMerBank" g="-109,-22"/> </join> <end g="332,582,48,52" name="end1"/> </process>

上面对应了6个处理类,实现分别如下所示:

package com.umpay.workflow.jbpm.handler; import java.util.Map; import org.jbpm.api.activity.ActivityBehaviour; import org.jbpm.api.activity.ActivityExecution; public class CheckCustomerHandler implements ActivityBehaviour { @Override public void execute(ActivityExecution execution) throws Exception { Map<String, Object> myRequest = (Map<String, Object>)execution.getVariable("myRequest"); String mobileId = (String)myRequest.get("mobileId"); // get system user id : userId=20110001674 myRequest.put("userId", "20110001674"); execution.setVariables(myRequest); } }

package com.umpay.workflow.jbpm.handler; import java.util.Map; import org.jbpm.api.activity.ActivityBehaviour; import org.jbpm.api.activity.ActivityExecution; public class CheckMerHandler implements ActivityBehaviour { @Override public void execute(ActivityExecution execution) throws Exception { Map<String, Object> myRequest = (Map<String, Object>)execution.getVariable("myRequest"); String mobileId = (String)myRequest.get("mobileId"); // get system user id : userId=20110001674 myRequest.put("userId", "20110001674"); execution.setVariables(myRequest); } }

package com.umpay.workflow.jbpm.handler; import java.util.Map; import org.jbpm.api.activity.ActivityBehaviour; import org.jbpm.api.activity.ActivityExecution; public class CheckBankHandler implements ActivityBehaviour { @Override public void execute(ActivityExecution execution) throws Exception { Map<String, Object> myRequest = (Map<String, Object>)execution.getVariable("myRequest"); String mobileId = (String)myRequest.get("mobileId"); // get system user id : userId=20110001674 myRequest.put("userId", "20110001674"); execution.setVariables(myRequest); } }

package com.umpay.workflow.jbpm.handler; import java.util.Map; import org.jbpm.api.activity.ActivityBehaviour; import org.jbpm.api.activity.ActivityExecution; public class CheckGoodsHandler implements ActivityBehaviour { @Override public void execute(ActivityExecution execution) throws Exception { Map<String, Object> myRequest = (Map<String, Object>)execution.getVariable("myRequest"); String goodsId = (String)myRequest.get("goodsId"); // get goods count myRequest.put("goodsCount", "2000"); execution.setVariables(myRequest); } }

package com.umpay.workflow.jbpm.handler; import java.util.Map; import org.jbpm.api.activity.ActivityBehaviour; import org.jbpm.api.activity.ActivityExecution; public class CheckMerBankHandler implements ActivityBehaviour { @Override public void execute(ActivityExecution execution) throws Exception { Map<String, Object> myRequest = (Map<String, Object>)execution.getVariable("myRequest"); String merId = (String)myRequest.get("merId"); String bankId = (String)myRequest.get("bankId"); // get mer bank relationship myRequest.put("mbr","mbr_" + merId + "_" + bankId); execution.setVariables(myRequest); } }

package com.umpay.workflow.jbpm.handler; import java.util.Map; import org.jbpm.api.activity.ActivityBehaviour; import org.jbpm.api.activity.ActivityExecution; public class CheckGoodsBankHandler implements ActivityBehaviour { @Override public void execute(ActivityExecution execution) throws Exception { Map<String, Object> myRequest = (Map<String, Object>)execution.getVariable("myRequest"); String goodsId = (String)myRequest.get("goodsId"); String bankId = (String)myRequest.get("bankId"); // get goods bank relationship myRequest.put("gbr", "gbr_" + goodsId + "_" + bankId); execution.setVariables(myRequest); } }

在执行子流程的过程中,在每一个节点处处理,都模拟了“获取到一些额外的必需数据”。

最后,测试用例。

测试用例,如下所示:

package com.umpay.workflow.jbpm.process; import java.util.HashMap; import java.util.Map; import junit.framework.TestCase; import org.jbpm.api.Execution; import org.jbpm.api.ProcessEngine; import org.jbpm.api.ProcessInstance; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainProcessTest extends TestCase { private ProcessEngine processEngine; private String mainProcessDeploymentId; private String subCheckProcessDeploymentId; protected void setUp() throws Exception { super.setUp(); ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext( "applicationContext.xml"); ctx.start(); this.processEngine = (ProcessEngine) ctx.getBean("processEngine"); mainProcessDeploymentId = this.processEngine .getRepositoryService() .createDeployment() .addResourceFromClasspath( "com/umpay/workflow/jbpm/jpdl/main-process.jpdl.xml") .deploy(); subCheckProcessDeploymentId = this.processEngine .getRepositoryService() .createDeployment() .addResourceFromClasspath( "com/umpay/workflow/jbpm/jpdl/sub-check-process.jpdl.xml") .deploy(); } protected void tearDown() throws Exception { this.processEngine.getRepositoryService().deleteDeploymentCascade( mainProcessDeploymentId); this.processEngine.getRepositoryService().deleteDeploymentCascade( subCheckProcessDeploymentId); super.tearDown(); } public void testMyProcess() { // initialize request data Map<String, Object> myRequest = new HashMap<String, Object>(); myRequest.put("merId", "001"); myRequest.put("mobileId", "13800138000"); myRequest.put("goodsId", "030"); myRequest.put("bankId", "CMPAY010"); Map<String, Object> variables = new HashMap<String, Object>(); variables.put("myRequest", myRequest); ProcessInstance processInstance = null; // start a process instance // it can execute a process automatically processInstance = this.processEngine .getExecutionService().startProcessInstanceByKey("MainProcess", variables); assertEquals(Execution.STATE_ENDED, processInstance.getState()); } }

上述程序,开始要需要部署流程,主流程和子流程需要单独部署,实际是在这个具体的例子中,存在两个流程,它们在执行自己的实例的时候是独立的。在流程启动之前,需要根据流程执行需要,输入在流程中能够获取到的数据(Key+Value的形式)。接着就可以运行了,可以看到,最终可以看到流程数据的集合 :

Main process variables: {goodsId=030, mobileId=13800138000, userId=20110001674, merId=001, goodsCount=2000, mbr=mbr_001_CMPAY010, gbr=gbr_030_CMPAY010, bankId=CMPAY010}

这里,数据集合{userId=20110001674, goodsCount=2000, mbr=mbr_001_CMPAY010, gbr=gbr_030_CMPAY010}都是在执行处理的时候获取到的交易操作所需要的数据。

你可能感兴趣的:(exception,object,String,Class,transition,variables)