場景:本章主要描述 下一節(jié)點為調(diào)用子流程 如何進行回退操作。
調(diào)用式子流程上一章:flowable 上一節(jié)點任務(wù)撤回-(5)嵌入式子流程
環(huán)境:
springboot:2.2.0.RELEASE
flowable:6.4.2git地址:https://github.com/oldguys/flowable-modeler-demo/tree/branch_with_flowable_examples
所有章節(jié):
主流程:
被調(diào)用流程:
調(diào)用式 子流程實質(zhì)流程 2個獨立流程 屿聋,只不過一個流程的 SuperExecution是另一個節(jié)點的 executionId空扎,在子流程完成之后,觸發(fā)主流程的execution完成
NextCallActivityRollbackOperateStrategy:調(diào)用子流程 撤回策略
步驟:
- 判斷下一節(jié)點的流程任務(wù)是否已經(jīng)完成润讥,可以利用接口:(原理是:頂級Execution的 ID 實質(zhì)就行 ProcessInstance Id 的特性進行處理)
callActivityExecutionList = > CommandContextUtil.getExecutionEntityManager(commandContext) .findExecutionsByParentExecutionAndActivityIds(hisTask.getProcessInstanceId(), Collections.singletonList(callActivity.getId())); // callActivity 在 父級流程的 executionId = 子流程的 processInstanceId ExecutionEntity executionEntity = callActivityExecutionList.get(0);
找到子流程的流程實例之后勺卢,對獲取已完成任務(wù)列表就輕松多了。然后采取之前的邏輯象对,如果未進行任務(wù)操作黑忱,則可以進行回退的前置條件。
- 創(chuàng)建任務(wù) execution勒魔,與普通節(jié)點一致甫煞,注意像SubProcess從相鄰節(jié)點獲取Execution,畢竟原來任務(wù)executio已經(jīng)消失冠绢。
- 刪除正在執(zhí)行任務(wù)抚吠,注意需要把 頂級節(jié)點 Execution和 主流程的 execution刪除。
- 處理相關(guān)數(shù)據(jù)
基于模板方法模式弟胀,構(gòu)建編寫通用 RollbackOperateStrategy.process() 操作
@Override
public void process(CommandContext commandContext, String assignee, Map<String, Object> variables) {
this.commandContext = commandContext;
this.assignee = assignee;
this.variables = variables;
log.info("處理 existNextFinishedTask");
existNextFinishedTask();
log.info("配置任務(wù)執(zhí)行人 setAssignee");
setAssignee();
log.info("處理 createExecution");
createExecution();
log.info("處理 deleteRuntimeTasks");
deleteRuntimeTasks();
log.info("處理 deleteHisActInstance");
deleteHisActInstance();
}
判斷已完成任務(wù)策略 existNextFinishedTask()
@Override
public void existNextFinishedTask() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
Map<String, CallActivity> callActivityMap = paramsTemplate.getCallActivityMap();
String key = callActivityMap.keySet().iterator().next();
this.callActivity = callActivityMap.get(key);
// 下一節(jié)點callActivity的 flowId
callActivityExecutionList = CommandContextUtil.getExecutionEntityManager(commandContext)
.findExecutionsByParentExecutionAndActivityIds(hisTask.getProcessInstanceId(), Collections.singletonList(callActivity.getId()));
// callActivity 在 父級流程的 executionId = 子流程的 processInstanceId
ExecutionEntity executionEntity = callActivityExecutionList.get(0);
// 子流程
callActivityProcess = CommandContextUtil.getExecutionEntityManager(commandContext)
.findSubProcessInstanceBySuperExecutionId(executionEntity.getId());
List<HistoricTaskInstance> hisTaskList = CommandContextUtil.getHistoricTaskService(commandContext)
.findHistoricTaskInstancesByQueryCriteria(
(HistoricTaskInstanceQueryImpl) new HistoricTaskInstanceQueryImpl()
.finished()
.processInstanceId(callActivityProcess.getId())
);
if (!hisTaskList.isEmpty()) {
throw new FlowableRuntimeException("子流程已經(jīng)具有完成的任務(wù),流程無法回退");
}
}
createExecution()
@Override
public void createExecution() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
ExecutionEntity executionEntity = CommandContextUtil.getExecutionEntityManager(commandContext)
.findById(hisTask.getExecutionId());
if (null == executionEntity) {
log.info("沒有找到execution");
executionEntity = callActivityExecutionList.get(0);
}
ExecutionEntity newExecution = CommandContextUtil.getExecutionEntityManager(commandContext)
.createChildExecution(executionEntity.getParent());
// 創(chuàng)建新任務(wù)
createExecution(newExecution);
// 移除歷史任務(wù)
removeHisTask(hisTask);
}
清除已經(jīng)生成任務(wù)
@Override
public void deleteRuntimeTasks() {
ExecutionEntity parentExecution = callActivityExecutionList.get(0);
// 清理子流程
cleanCallActivityProcessInstance(callActivityProcess);
// 清理主流程記錄
CommandContextUtil.getExecutionEntityManager(commandContext)
.delete(parentExecution);
}
/**
* // 無效操作
* CommandContextUtil.getExecutionEntityManager(commandContext)
* .deleteProcessInstance(callActivityProcess.getId(), "進行流程撤回", false);
* 清理 調(diào)用子流程 相關(guān)數(shù)據(jù)
*
* @param processInstance
*/
private void cleanCallActivityProcessInstance(ExecutionEntity processInstance) {
// 移除正在運行任務(wù)信息
List<Task> list = CommandContextUtil.getTaskService(commandContext)
.createTaskQuery()
.processInstanceId(processInstance.getId())
.list();
list.forEach(obj->removeRuntimeTaskOperate((TaskEntity) obj));
// 移除歷史任務(wù)信息
List<HistoricTaskInstanceEntity> historicTaskInstanceList = CommandContextUtil.getHistoricTaskService(commandContext)
.findHistoricTasksByProcessInstanceId(processInstance.getId());
historicTaskInstanceList.forEach(obj->CommandContextUtil.getHistoricTaskService(commandContext).deleteHistoricTask(obj));
// 移除 子流程實例
CommandContextUtil.getIdentityLinkService(commandContext).deleteIdentityLinksByProcessInstanceId(processInstance.getId());
CommandContextUtil.getVariableService(commandContext).deleteVariablesByExecutionId(processInstance.getId());
CommandContextUtil.getExecutionEntityManager(commandContext).delete(processInstance.getId());
}
以上 完成對 上一節(jié)點任務(wù)撤回 架構(gòu)設(shè)計 及 第 6 種情況 解決方案講述楷力。
git地址:https://github.com/oldguys/flowable-modeler-demo/tree/branch_with_flowable_examples
總結(jié):
基本上流程撤回的實現(xiàn)思路就是圍繞著:模擬數(shù)據(jù)流喊式,難點在于需要分析比較幾種主要節(jié)點的特性,當節(jié)點特性本質(zhì)熟悉之后萧朝〔砹簦基于這5大類進行組合重寫策略就能解決更加復(fù)雜的場景,見招拆招检柬,以數(shù)據(jù)流本質(zhì)應(yīng)萬變就行献联。