一、什么是多實(shí)例減簽,多實(shí)例加簽
比如配置了一個(gè)多實(shí)例用戶實(shí)例闷堡,由三人串行或者并行執(zhí)行,那么現(xiàn)在的需求是某個(gè)個(gè)例不需要那么多人了疑故,只需要兩個(gè)人也就是減少一個(gè)人杠览,這樣的操作稱為減簽操作。
反之纵势,當(dāng)需要添加一個(gè)人員參與會(huì)簽時(shí)的操作踱阿,就稱之為加簽操作。
二吨悍、多實(shí)例減簽(僅支持6版本)
思路
通過(guò)多實(shí)例運(yùn)轉(zhuǎn)過(guò)程很容易能夠理清如何實(shí)現(xiàn)減簽操作,如果需要明白運(yùn)轉(zhuǎn)過(guò)程可以參考activiti6.0源碼剖析之多實(shí)例運(yùn)轉(zhuǎn)過(guò)程
以該流程圖為例說(shuō)明
減簽可以從兩種角度去看:被減掉的是以已經(jīng)執(zhí)行成功來(lái)做蹋嵌,還是壓根就當(dāng)作沒(méi)有存在過(guò)
根據(jù)上述兩種角度可以大致理清以下思路
首先根據(jù)需要減掉的任務(wù)Id獲取到該任務(wù)ID所屬的三級(jí)執(zhí)行實(shí)例
然后根據(jù)三級(jí)執(zhí)行實(shí)例ID或者多多實(shí)例執(zhí)行實(shí)例的父級(jí)實(shí)例(二級(jí)實(shí)例)
通過(guò)二級(jí)執(zhí)行實(shí)例刪除需要減掉的三級(jí)執(zhí)行實(shí)例數(shù)據(jù)育瓜,任務(wù)數(shù)據(jù)
-
根據(jù)二級(jí)執(zhí)行實(shí)例獲取nrOfInstances,nrOfCompletedInstances,nrOfActiveInstances,loopCounter變量栽烂,并根據(jù)并行或者串行多實(shí)例躏仇,根據(jù)上述兩種角度進(jìn)行相應(yīng)的變更
如果是串行多實(shí)例減簽
正常執(zhí)行完成的角度上:nrOfCompletedInstances 加 1,nrOfActiveInstances保持1不變腺办,loopCounter 加 1
非正常完成的角度上:nrOfInstances 減 1焰手,loopCounter 加 1如果是并行多實(shí)例減簽
正常執(zhí)行完成的角度上:nrOfCompletedInstances 加 1,nrOfActiveInstances 減 1怀喉,
非正常完成的角度上:nrOfInstances 減 1书妻,nrOfActiveInstances 減 1,
實(shí)戰(zhàn)
public class DeleteMultiInstanceCmd implements Command {
protected final String NUMBER_OF_INSTANCES = "nrOfInstances";
protected final String NUMBER_OF_ACTIVE_INSTANCES = "nrOfActiveInstances";
protected final String NUMBER_OF_COMPLETED_INSTANCES = "nrOfCompletedInstances";
protected String collectionElementIndexVariable = "loopCounter";
private String taskId;
private Boolean isNormalComplete;
public DeleteMultiInstanceCmd(String taskId,boolean isNormalComplete) {
this.taskId = taskId;
this.isNormalComplete = isNormalComplete;
}
public Object execute(CommandContext commandContext) {
ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
TaskEntityManager taskEntityManager = commandContext.getTaskEntityManager();
//根據(jù)任務(wù)id獲取任務(wù)實(shí)例
TaskEntity taskEntity = taskEntityManager.findById(taskId);
//根據(jù)執(zhí)行實(shí)例ID獲取三級(jí)執(zhí)行實(shí)例
ExecutionEntity execution = executionEntityManager.findById(taskEntity.getExecutionId());
//首先判斷當(dāng)前任務(wù)是否是屬于多實(shí)例節(jié)點(diǎn)
String processDefinitionId = execution.getProcessDefinitionId();
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processDefinitionId);
Activity activityElement = (Activity)bpmnModel.getFlowElement(execution.getCurrentActivityId());
MultiInstanceLoopCharacteristics loopCharacteristics = activityElement.getLoopCharacteristics();
if(loopCharacteristics == null){
throw new RuntimeException("沒(méi)有找到多實(shí)例");
}
if(!(activityElement.getBehavior() instanceof MultiInstanceActivityBehavior)){
throw new RuntimeException("此節(jié)點(diǎn)不是多實(shí)例節(jié)點(diǎn)");
}
DeploymentManager deploymentManager = commandContext.getProcessEngineConfiguration().getDeploymentManager();
ProcessDefinition definition = deploymentManager.findDeployedProcessDefinitionById(processDefinitionId);
//判斷是否是5的版本
if(Activiti5Util.isActiviti5ProcessDefinition(commandContext,definition)){
throw new RuntimeException("不支持5版本");
}
boolean isSequential = loopCharacteristics.isSequential();
//獲取二級(jí)執(zhí)行實(shí)例
ExecutionEntity sencondExecution = execution.getParent();
//刪除所要?jiǎng)h除的實(shí)例相關(guān)數(shù)據(jù)
if(!isSequential){
//并行多實(shí)例
executionEntityManager.deleteChildExecutions(execution,"減簽",false);
executionEntityManager.deleteExecutionAndRelatedData(execution,"減簽",true);
}
//獲取二級(jí)執(zhí)行實(shí)例關(guān)聯(lián)的變量
Integer nrOfInstances = (Integer) sencondExecution.getVariable(NUMBER_OF_INSTANCES);
Integer nrOfActiveInstances = (Integer) sencondExecution.getVariable(NUMBER_OF_ACTIVE_INSTANCES);
Integer nrOfCompletedInstances = (Integer) sencondExecution.getVariable(NUMBER_OF_COMPLETED_INSTANCES);
//更新二級(jí)執(zhí)行實(shí)例關(guān)聯(lián)的變量
if(isNormalComplete){
//正常完成
sencondExecution.setVariable(NUMBER_OF_COMPLETED_INSTANCES,nrOfCompletedInstances+1 );
if(isSequential){
//串行多實(shí)例
Integer loopCounter =getLoopVariable(execution,collectionElementIndexVariable);
execution.setVariableLocal(collectionElementIndexVariable,loopCounter+1);
}else{
//并行多實(shí)例
sencondExecution.setVariableLocal(NUMBER_OF_ACTIVE_INSTANCES,nrOfActiveInstances-1);
}
}else{
//非正常(就當(dāng)作沒(méi)有過(guò)此任務(wù))
sencondExecution.setVariableLocal(NUMBER_OF_INSTANCES,nrOfInstances-1);
if(isSequential){
//串行多實(shí)例
Integer loopCounter = (Integer) execution.getVariable(collectionElementIndexVariable);
execution.setVariableLocal(collectionElementIndexVariable,loopCounter+1);
}else{
//并行多實(shí)例
//并行多實(shí)例
sencondExecution.setVariableLocal(NUMBER_OF_ACTIVE_INSTANCES,nrOfActiveInstances-1);
}
}
//刪除任務(wù)
taskEntityManager.delete(taskId);
//觸發(fā)流程運(yùn)轉(zhuǎn)
ActivitiEngineAgenda agenda = commandContext.getAgenda();
agenda.planContinueProcessInCompensation(execution);
return null;
}
protected Integer getLoopVariable(DelegateExecution execution, String variableName) {
Object value = execution.getVariableLocal(variableName);
DelegateExecution parent = execution.getParent();
while (value == null && parent != null) {
value = parent.getVariableLocal(variableName);
parent = parent.getParent();
}
return (Integer) (value != null ? value : 0);
}
}
三躬拢、并行多實(shí)例加簽
思路
- 根據(jù)業(yè)務(wù)需求獲取到多實(shí)例父級(jí)執(zhí)行實(shí)例
- 判斷當(dāng)前節(jié)點(diǎn)是否是并行多實(shí)例
- 根據(jù)多實(shí)例父級(jí)實(shí)例創(chuàng)建多實(shí)例執(zhí)行實(shí)例(也就是新加的人員所在執(zhí)行實(shí)例)
- 為新建的多實(shí)例執(zhí)行實(shí)例設(shè)置當(dāng)前處理節(jié)點(diǎn)
- 更改多實(shí)例父級(jí)執(zhí)行實(shí)例的變量
nrOfInstances+1
nrOfActiveInstances+1 - 通知該活動(dòng)開(kāi)始
- 獲取行為類
- 執(zhí)行行為類
實(shí)戰(zhàn)
public class AddMultiInstanceCmd implements Command {
protected final String NUMBER_OF_INSTANCES = "nrOfInstances";
protected final String NUMBER_OF_ACTIVE_INSTANCES = "nrOfActiveInstances";
private String multiRootExecutionId;
private String addUserTaskAssign;
public AddMultiInstanceCmd(String multiRootExecutionId, String addUserTaskAssign) {
this.multiRootExecutionId = multiRootExecutionId;
this.addUserTaskAssign = addUserTaskAssign;
}
public Object execute(CommandContext commandContext) {
ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
//獲取多實(shí)例父級(jí)執(zhí)行實(shí)例
ExecutionEntity multiExecutionEntity = executionEntityManager.findById(multiRootExecutionId);
//判斷當(dāng)前執(zhí)行實(shí)例的節(jié)點(diǎn)是否是多實(shí)例節(jié)點(diǎn)
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(multiExecutionEntity.getProcessDefinitionId());
Activity miActivityElement = (Activity) bpmnModel.getFlowElement(multiExecutionEntity.getCurrentActivityId());
MultiInstanceLoopCharacteristics loopCharacteristics = miActivityElement.getLoopCharacteristics();
if(loopCharacteristics == null){
throw new ActivitiException("此節(jié)點(diǎn)不是多實(shí)例節(jié)點(diǎn)");
}
//判斷是否是并行多實(shí)例
if(loopCharacteristics.isSequential()){
throw new ActivitiException("此節(jié)點(diǎn)為串行節(jié)點(diǎn)");
}
//創(chuàng)建新的子實(shí)例
ExecutionEntity childExecution = executionEntityManager.createChildExecution(multiExecutionEntity);
//獲取并為新的執(zhí)行實(shí)例設(shè)置當(dāng)前活動(dòng)節(jié)點(diǎn)
UserTask currentFlowElement = (UserTask) multiExecutionEntity.getCurrentFlowElement();
//設(shè)置處理人
currentFlowElement.setAssignee(addUserTaskAssign);
childExecution.setCurrentFlowElement(currentFlowElement);
//獲取設(shè)置變量
Integer nrOfInstances = (Integer) multiExecutionEntity.getVariableLocal(NUMBER_OF_INSTANCES);
Integer nrOfActiveInstances = (Integer) multiExecutionEntity.getVariableLocal(NUMBER_OF_ACTIVE_INSTANCES);
multiExecutionEntity.setVariableLocal(NUMBER_OF_INSTANCES,nrOfInstances+1);
multiExecutionEntity.setVariableLocal(NUMBER_OF_ACTIVE_INSTANCES,nrOfActiveInstances+1);
//通知活動(dòng)開(kāi)始
HistoryManager historyManager = commandContext.getHistoryManager();
historyManager.recordActivityStart(childExecution);
//獲取處理行為類
ParallelMultiInstanceBehavior prallelMultiInstanceBehavior = (ParallelMultiInstanceBehavior) miActivityElement.getBehavior();
AbstractBpmnActivityBehavior innerActivityBehavior = prallelMultiInstanceBehavior.getInnerActivityBehavior();
//執(zhí)行
innerActivityBehavior.execute(childExecution);
return null;
}
}