flowable之回调活动(子流程)
描述
尽管看起来很相像,但在BPMN 2.0中,调用活动(call activity)有别于一般的子流程——通常也称作嵌入式子流程。从概念上说,两者都在流程执行到达该活动时,调用一个子流程。
两者的区别为,调用活动引用一个流程定义外部的流程,而子流程嵌入在原有流程定义内。调用活动的主要使用场景是,在多个不同流程定义中调用一个可复用的流程定义。
当流程执行到达调用活动时,会创建一个新的执行,作为到达调用活动的执行的子执行。这个子执行用于执行子流程,也可用于创建并行子执行(与普通流程中行为类似)。父执行将等待子流程完成,之后沿原流程继续执行。
流转过程种涉及到的类
- org.flowable.engine.impl.agenda.ContinueProcessOperation
- org.flowable.engine.impl.agenda.EndExecutionOperation;
具体执行过程
调用上面提到的类的run方法
public void run() {
if (this.execution.isProcessInstanceType()) {
this.handleProcessInstanceExecution(this.execution);
} else {
this.handleRegularExecution();
}
}
protected void handleRegularExecution() {
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(this.commandContext);
ExecutionEntityManager executionEntityManager = processEngineConfiguration.getExecutionEntityManager();
ExecutionEntity parentExecution = (ExecutionEntity)executionEntityManager.findById(this.execution.getParentId());
if (this.execution.isScope()) {
executionEntityManager.deleteChildExecutions(this.execution, (String)null, false);
}
LOGGER.debug("Ending execution {}", this.execution.getId());
executionEntityManager.deleteExecutionAndRelatedData(this.execution, (String)null, false);
LOGGER.debug("Parent execution found. Continuing process using execution {}", parentExecution.getId());
if (this.isEndEventInMultiInstanceSubprocess(this.execution)) {
this.handleMultiInstanceSubProcess(executionEntityManager, parentExecution, this.execution);
} else {
SubProcess subProcess = this.execution.getCurrentFlowElement().getSubProcess();
ExecutionEntity executionToContinue;
if (subProcess instanceof EventSubProcess) {
EventSubProcess eventSubProcess = (EventSubProcess)subProcess;
boolean hasNonInterruptingStartEvent = false;
Iterator var7 = eventSubProcess.getFlowElements().iterator();
while(var7.hasNext()) {
FlowElement eventSubElement = (FlowElement)var7.next();
if (eventSubElement instanceof StartEvent) {
StartEvent subStartEvent = (StartEvent)eventSubElement;
if (!subStartEvent.isInterrupting()) {
hasNonInterruptingStartEvent = true;
break;
}
}
}
if (hasNonInterruptingStartEvent) {
executionEntityManager.deleteChildExecutions(parentExecution, (String)null, false);
executionEntityManager.deleteExecutionAndRelatedData(parentExecution, (String)null, false);
CommandContextUtil.getEventDispatcher(this.commandContext).dispatchEvent(FlowableEventBuilder.createActivityEvent(FlowableEngineEventType.ACTIVITY_COMPLETED, subProcess.getId(), subProcess.getName(), parentExecution.getId(), parentExecution.getProcessInstanceId(), parentExecution.getProcessDefinitionId(), subProcess), processEngineConfiguration.getEngineCfgKey());
ExecutionEntity subProcessParentExecution = parentExecution.getParent();
if (this.getNumberOfActiveChildExecutionsForExecution(executionEntityManager, subProcessParentExecution.getId()) == 0) {
if (subProcessParentExecution.getCurrentFlowElement() instanceof SubProcess) {
SubProcess parentSubProcess = (SubProcess)subProcessParentExecution.getCurrentFlowElement();
if (parentSubProcess.getOutgoingFlows().size() > 0) {
executionToContinue = this.handleSubProcessEnd(executionEntityManager, subProcessParentExecution, parentSubProcess);
this.agenda.planTakeOutgoingSequenceFlowsOperation(executionToContinue, true);
return;
}
}
this.agenda.planEndExecutionOperation(subProcessParentExecution);
}
return;
}
}
List<ExecutionEntity> eventScopeExecutions = this.getEventScopeExecutions(executionEntityManager, parentExecution);
if (!eventScopeExecutions.isEmpty()) {
List<? extends ExecutionEntity> childExecutions = parentExecution.getExecutions();
boolean activeSiblings = false;
Iterator var15 = childExecutions.iterator();
while(var15.hasNext()) {
executionToContinue = (ExecutionEntity)var15.next();
if (!this.isInEventSubProcess(executionToContinue) && executionToContinue.isActive() && !executionToContinue.isEnded()) {
activeSiblings = true;
}
}
if (!activeSiblings) {
var15 = eventScopeExecutions.iterator();
while(var15.hasNext()) {
executionToContinue = (ExecutionEntity)var15.next();
executionEntityManager.deleteExecutionAndRelatedData(executionToContinue, (String)null, false);
}
}
}
if (this.getNumberOfActiveChildExecutionsForExecution(executionEntityManager, parentExecution.getId()) == 0) {
ExecutionEntity executionToContinue = null;
if (subProcess != null) {
if (subProcess.isForCompensation()) {
this.agenda.planEndExecutionOperation(parentExecution);
} else {
executionToContinue = this.handleSubProcessEnd(executionEntityManager, parentExecution, subProcess);
}
} else {
executionToContinue = this.handleRegularExecutionEnd(executionEntityManager, parentExecution);
}
if (executionToContinue != null) {
if (executionToContinue.isProcessInstanceType()) {
this.handleProcessInstanceExecution(executionToContinue);
} else {
this.agenda.planTakeOutgoingSequenceFlowsOperation(executionToContinue, true);
}
}
}
}
}
protected void handleProcessInstanceExecution(ExecutionEntity processInstanceExecution) {
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(this.commandContext);
String processInstanceId = processInstanceExecution.getId();
LOGGER.debug("No parent execution found. Verifying if process instance {} can be stopped.", processInstanceId);
ExecutionEntity superExecution = processInstanceExecution.getSuperExecution();
if (!this.forceSynchronous && this.isAsyncCompleteCallActivity(superExecution)) {
this.scheduleAsyncCompleteCallActivity(superExecution, processInstanceExecution);
} else {
SubProcessActivityBehavior subProcessActivityBehavior = null;
if (superExecution != null) {
FlowNode superExecutionElement = (FlowNode)superExecution.getCurrentFlowElement();
subProcessActivityBehavior = (SubProcessActivityBehavior)superExecutionElement.getBehavior();
try {
subProcessActivityBehavior.completing(superExecution, processInstanceExecution);
} catch (RuntimeException var11) {
LOGGER.error("Error while completing sub process of execution {}", processInstanceExecution, var11);
throw var11;
} catch (Exception var12) {
LOGGER.error("Error while completing sub process of execution {}", processInstanceExecution, var12);
throw new FlowableException("Error while completing sub process of execution " + processInstanceExecution, var12);
}
}
int activeExecutions = this.getNumberOfActiveChildExecutionsForProcessInstance(executionEntityManager, processInstanceId);
if (activeExecutions == 0) {
LOGGER.debug("No active executions found. Ending process instance {}", processInstanceId);
executionEntityManager.deleteProcessInstanceExecutionEntity(processInstanceId, this.execution.getCurrentFlowElement() != null ? this.execution.getCurrentFlowElement().getId() : null, (String)null, false, false, true);
} else {
LOGGER.debug("Active executions found. Process instance {} will not be ended.", processInstanceId);
}
Process process = ProcessDefinitionUtil.getProcess(processInstanceExecution.getProcessDefinitionId());
if (CollectionUtil.isNotEmpty(process.getExecutionListeners())) {
this.executeExecutionListeners(process, processInstanceExecution, "end");
}
if (superExecution != null) {
superExecution.setSubProcessInstance((ExecutionEntity)null);
try {
subProcessActivityBehavior.completed(superExecution);
} catch (RuntimeException var9) {
LOGGER.error("Error while completing sub process of execution {}", processInstanceExecution, var9);
throw var9;
} catch (Exception var10) {
LOGGER.error("Error while completing sub process of execution {}", processInstanceExecution, var10);
throw new FlowableException("Error while completing sub process of execution " + processInstanceExecution, var10);
}
}
}
}