protected internal virtual void ExecuteNonInterruptingBehavior(IExecutionEntity executionEntity, ICommandContext commandContext) { // Non-interrupting: the current execution is given the first parent // scope (which isn't its direct parent) // // Why? Because this execution does NOT have anything to do with // the current parent execution (the one where the boundary event is on): when it is deleted or whatever, // this does not impact this new execution at all, it is completely independent in that regard. // Note: if the parent of the parent does not exists, this becomes a concurrent execution in the process instance! IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager; IExecutionEntity parentExecutionEntity = executionEntityManager.FindById <IExecutionEntity>(executionEntity.ParentId); IExecutionEntity scopeExecution = null; IExecutionEntity currentlyExaminedExecution = executionEntityManager.FindById <IExecutionEntity>(parentExecutionEntity.ParentId); GetScopeExecution(executionEntityManager, ref scopeExecution, ref currentlyExaminedExecution); if (scopeExecution == null) { throw new ActivitiException("Programmatic error: no parent scope execution found for boundary event"); } IExecutionEntity nonInterruptingExecution = executionEntityManager.CreateChildExecution(scopeExecution); nonInterruptingExecution.CurrentFlowElement = executionEntity.CurrentFlowElement; Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(nonInterruptingExecution, true); }
/// <summary> /// we create a separate execution for each compensation handler invocation. /// </summary> public static void ThrowCompensationEvent(IList <ICompensateEventSubscriptionEntity> eventSubscriptions, IExecutionEntity execution, bool async) { IExecutionEntityManager executionEntityManager = Context.CommandContext.ExecutionEntityManager; // first spawn the compensating executions foreach (IEventSubscriptionEntity eventSubscription in eventSubscriptions) { IExecutionEntity compensatingExecution = null; // check whether compensating execution is already created (which is the case when compensating an embedded subprocess, // where the compensating execution is created when leaving the subprocess and holds snapshot data). if (eventSubscription.Configuration is object) { compensatingExecution = executionEntityManager.FindById <IExecutionEntity>(eventSubscription.Configuration); compensatingExecution.Parent = compensatingExecution.ProcessInstance; compensatingExecution.IsEventScope = false; } else { compensatingExecution = executionEntityManager.CreateChildExecution(execution); eventSubscription.Configuration = compensatingExecution.Id; } } // signal compensation events in reverse order of their 'created' timestamp eventSubscriptions.OrderBy(x => x, new ComparatorAnonymousInnerClass()); foreach (ICompensateEventSubscriptionEntity compensateEventSubscriptionEntity in eventSubscriptions) { Context.CommandContext.EventSubscriptionEntityManager.EventReceived(compensateEventSubscriptionEntity, null, async); } }
public virtual object Execute(ICommandContext commandContext) { IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager; IExecutionEntity execution = executionEntityManager.FindById <IExecutionEntity>(executionId); if (execution == null) { throw new ActivitiObjectNotFoundException("No execution found for id '" + executionId + "'", typeof(IExecutionEntity)); } if (!(execution.CurrentFlowElement is AdhocSubProcess)) { throw new ActivitiException("The current flow element of the requested execution is not an ad-hoc sub process"); } IList <IExecutionEntity> childExecutions = execution.Executions; if (childExecutions.Count > 0) { throw new ActivitiException("Ad-hoc sub process has running child executions that need to be completed first"); } IExecutionEntity outgoingFlowExecution = executionEntityManager.CreateChildExecution(execution.Parent); outgoingFlowExecution.CurrentFlowElement = execution.CurrentFlowElement; executionEntityManager.DeleteExecutionAndRelatedData(execution, null, false); Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(outgoingFlowExecution, true); return(null); }
public override void Leave(IExecutionEntity childExecution, object signalData) { completedPolicy.LeaveExection = childExecution; IExecutionEntity multiInstanceRootExecution = GetMultiInstanceRootExecution(childExecution); int nrOfInstances = GetLoopVariable(multiInstanceRootExecution, NUMBER_OF_INSTANCES).GetValueOrDefault(0); int loopCounter = GetLoopVariable(childExecution, CollectionElementIndexVariable).GetValueOrDefault(0) + 1; int nrOfCompletedInstances = GetLoopVariable(multiInstanceRootExecution, NUMBER_OF_COMPLETED_INSTANCES).GetValueOrDefault(0) + 1; int nrOfActiveInstances = GetLoopVariable(multiInstanceRootExecution, NUMBER_OF_ACTIVE_INSTANCES).GetValueOrDefault(0); SetLoopVariable(multiInstanceRootExecution, NUMBER_OF_COMPLETED_INSTANCES, nrOfCompletedInstances); SetLoopVariable(childExecution, CollectionElementIndexVariable, loopCounter); LogLoopDetails(childExecution, "instance completed", loopCounter, nrOfCompletedInstances, nrOfActiveInstances, nrOfInstances); Context.CommandContext.HistoryManager.RecordActivityEnd(childExecution, null); CallActivityEndListeners(childExecution); //executeCompensationBoundaryEvents(execution.getCurrentFlowElement(), execution); if (loopCounter >= nrOfInstances || CompletionConditionSatisfied(multiInstanceRootExecution, signalData)) { RemoveLocalLoopVariable(childExecution, CollectionElementIndexVariable); multiInstanceRootExecution.IsMultiInstanceRoot = false; multiInstanceRootExecution.IsScope = false; multiInstanceRootExecution.CurrentFlowElement = childExecution.CurrentFlowElement; Context.CommandContext.ExecutionEntityManager.DeleteChildExecutions(multiInstanceRootExecution, "MI_END", false); base.Leave(multiInstanceRootExecution, signalData); } else { try { if (childExecution.CurrentFlowElement is SubProcess) { IExecutionEntityManager executionEntityManager = Context.CommandContext.ExecutionEntityManager; IExecutionEntity executionToContinue = executionEntityManager.CreateChildExecution(multiInstanceRootExecution); executionToContinue.CurrentFlowElement = childExecution.CurrentFlowElement; executionToContinue.IsScope = true; SetLoopVariable(executionToContinue, CollectionElementIndexVariable, loopCounter); ExecuteOriginalBehavior(executionToContinue, loopCounter); } else { ExecuteOriginalBehavior(childExecution, loopCounter); } } catch (BpmnError error) { // re-throw business fault so that it can be caught by an Error // Intermediate Event or Error Event Sub-Process in the process throw error; } catch (Exception e) { throw new ActivitiException("Could not execute inner activity behavior of multi instance behavior", e); } } }
protected internal virtual void DefaultTerminateEndEventBehaviour(IExecutionEntity execution, ICommandContext commandContext, IExecutionEntityManager executionEntityManager) { IExecutionEntity scopeExecutionEntity = executionEntityManager.FindFirstScope(execution); SendProcessInstanceCancelledEvent(scopeExecutionEntity, execution.CurrentFlowElement); // If the scope is the process instance, we can just terminate it all // Special treatment is needed when the terminated activity is a subprocess (embedded/callactivity/..) // The subprocess is destroyed, but the execution calling it, continues further on. // In case of a multi-instance subprocess, only one instance is terminated, the other instances continue to exist. string deleteReason = CreateDeleteReason(execution.CurrentActivityId); if (scopeExecutionEntity.ProcessInstanceType && scopeExecutionEntity.SuperExecutionId is null) { EndAllHistoricActivities(scopeExecutionEntity.Id, deleteReason); DeleteExecutionEntities(executionEntityManager, scopeExecutionEntity, deleteReason); commandContext.HistoryManager.RecordProcessInstanceEnd(scopeExecutionEntity.Id, deleteReason, execution.CurrentActivityId); } else if (scopeExecutionEntity.CurrentFlowElement != null && scopeExecutionEntity.CurrentFlowElement is SubProcess) { // SubProcess SubProcess subProcess = (SubProcess)scopeExecutionEntity.CurrentFlowElement; scopeExecutionEntity.DeleteReason = deleteReason; if (subProcess.HasMultiInstanceLoopCharacteristics()) { Context.Agenda.PlanDestroyScopeOperation(scopeExecutionEntity); MultiInstanceActivityBehavior multiInstanceBehavior = (MultiInstanceActivityBehavior)subProcess.Behavior; multiInstanceBehavior.Leave(scopeExecutionEntity); } else { Context.Agenda.PlanDestroyScopeOperation(scopeExecutionEntity); IExecutionEntity outgoingFlowExecution = executionEntityManager.CreateChildExecution(scopeExecutionEntity.Parent); outgoingFlowExecution.CurrentFlowElement = scopeExecutionEntity.CurrentFlowElement; Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(outgoingFlowExecution, true); } } else if (scopeExecutionEntity.ParentId is null && scopeExecutionEntity.SuperExecutionId is object) { // CallActivity IExecutionEntity callActivityExecution = scopeExecutionEntity.SuperExecution; CallActivity callActivity = (CallActivity)callActivityExecution.CurrentFlowElement; if (callActivity.HasMultiInstanceLoopCharacteristics()) { MultiInstanceActivityBehavior multiInstanceBehavior = (MultiInstanceActivityBehavior)callActivity.Behavior; multiInstanceBehavior.Leave(callActivityExecution); executionEntityManager.DeleteProcessInstanceExecutionEntity(scopeExecutionEntity.Id, execution.CurrentFlowElement.Id, "terminate end event", false, false); } else { executionEntityManager.DeleteProcessInstanceExecutionEntity(scopeExecutionEntity.Id, execution.CurrentFlowElement.Id, "terminate end event", false, false); IExecutionEntity superExecutionEntity = executionEntityManager.FindById <IExecutionEntity>(scopeExecutionEntity.SuperExecutionId); Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(superExecutionEntity, true); } } }
/// <summary> /// /// </summary> /// <param name="executionEntityManager"></param> /// <param name="parentExecution"></param> /// <returns></returns> protected internal virtual IExecutionEntity HandleRegularExecutionEnd(IExecutionEntityManager executionEntityManager, IExecutionEntity parentExecution) { if (!parentExecution.ProcessInstanceType && !(parentExecution.CurrentFlowElement is SubProcess)) { parentExecution.CurrentFlowElement = execution.CurrentFlowElement; } IExecutionEntity executionToContinue; if (execution.CurrentFlowElement is SubProcess currentSubProcess) { if (currentSubProcess.OutgoingFlows.Count > 0) { // create a new execution to take the outgoing sequence flows executionToContinue = executionEntityManager.CreateChildExecution(parentExecution); executionToContinue.CurrentFlowElement = execution.CurrentFlowElement; } else { if (!parentExecution.Id.Equals(parentExecution.ProcessInstanceId)) { // create a new execution to take the outgoing sequence flows executionToContinue = executionEntityManager.CreateChildExecution(parentExecution.Parent); executionToContinue.CurrentFlowElement = parentExecution.CurrentFlowElement; executionEntityManager.DeleteChildExecutions(parentExecution, null, false); executionEntityManager.DeleteExecutionAndRelatedData(parentExecution, null, false); } else { executionToContinue = parentExecution; } } } else { executionToContinue = parentExecution; } return(executionToContinue); }
protected internal static void ExecuteEventHandler(Event @event, IExecutionEntity parentExecution, IExecutionEntity currentExecution, string errorId) { ProcessEngineConfigurationImpl processEngineConfiguration = Context.ProcessEngineConfiguration; if (processEngineConfiguration is object && processEngineConfiguration.EventDispatcher.Enabled) { BpmnModel bpmnModel = ProcessDefinitionUtil.GetBpmnModel(parentExecution.ProcessDefinitionId); if (bpmnModel != null) { bpmnModel.Errors.TryGetValue(errorId, out string errorCode); if (errorCode is null) { errorCode = errorId; } processEngineConfiguration.EventDispatcher.DispatchEvent(ActivitiEventBuilder.CreateErrorEvent(ActivitiEventType.ACTIVITY_ERROR_RECEIVED, @event.Id, errorId, errorCode, parentExecution.Id, parentExecution.ProcessInstanceId, parentExecution.ProcessDefinitionId)); } } if (@event is StartEvent) { IExecutionEntityManager executionEntityManager = Context.CommandContext.ExecutionEntityManager; if (!currentExecution.ParentId.Equals(parentExecution.Id)) { Context.Agenda.PlanDestroyScopeOperation(currentExecution); } else { executionEntityManager.DeleteExecutionAndRelatedData(currentExecution, null, false); } IExecutionEntity eventSubProcessExecution = executionEntityManager.CreateChildExecution(parentExecution); eventSubProcessExecution.CurrentFlowElement = @event; Context.Agenda.PlanContinueProcessOperation(eventSubProcessExecution); } else { IExecutionEntity boundaryExecution = null; IList <IExecutionEntity> childExecutions = parentExecution.Executions; foreach (IExecutionEntity childExecution in childExecutions) { if (childExecution.ActivityId.Equals(@event.Id)) { boundaryExecution = childExecution; } } Context.Agenda.PlanTriggerExecutionOperation(boundaryExecution); } }
/// <summary> /// /// </summary> /// <param name="executionEntityManager"></param> /// <param name="parentExecution"></param> /// <param name="subProcess"></param> /// <returns></returns> protected internal virtual IExecutionEntity HandleSubProcessEnd(IExecutionEntityManager executionEntityManager, IExecutionEntity parentExecution, SubProcess subProcess) { // create a new execution to take the outgoing sequence flows IExecutionEntity executionToContinue = executionEntityManager.CreateChildExecution(parentExecution.Parent); executionToContinue.CurrentFlowElement = subProcess; bool hasCompensation = false; if (subProcess is Transaction) { hasCompensation = true; } else { foreach (FlowElement subElement in subProcess.FlowElements) { if (subElement is Activity subActivity) { if (CollectionUtil.IsNotEmpty(subActivity.BoundaryEvents)) { foreach (BoundaryEvent boundaryEvent in subActivity.BoundaryEvents) { if (CollectionUtil.IsNotEmpty(boundaryEvent.EventDefinitions) && boundaryEvent.EventDefinitions[0] is CompensateEventDefinition) { hasCompensation = true; break; } } } } } } // All executions will be cleaned up afterwards. However, for compensation we need // a copy of these executions so we can use them later on when the compensation is thrown. // The following method does exactly that, and moves the executions beneath the process instance. if (hasCompensation) { ScopeUtil.CreateCopyOfSubProcessExecutionForCompensation(parentExecution); } executionEntityManager.DeleteChildExecutions(parentExecution, null, false); executionEntityManager.DeleteExecutionAndRelatedData(parentExecution, null, false); Context.ProcessEngineConfiguration.EventDispatcher.DispatchEvent(ActivitiEventBuilder.CreateActivityEvent(ActivitiEventType.ACTIVITY_COMPLETED, subProcess.Id, subProcess.Name, parentExecution.Id, parentExecution.ProcessInstanceId, parentExecution.ProcessDefinitionId, subProcess)); return(executionToContinue); }
protected internal virtual void TerminateMultiInstanceRoot(IExecutionEntity execution, ICommandContext commandContext, IExecutionEntityManager executionEntityManager) { // When terminateMultiInstance is 'true', we look for the multi instance root and delete it from there. IExecutionEntity miRootExecutionEntity = executionEntityManager.FindFirstMultiInstanceRoot(execution); if (miRootExecutionEntity != null) { // Create sibling execution to continue process instance execution before deletion IExecutionEntity siblingExecution = executionEntityManager.CreateChildExecution(miRootExecutionEntity.Parent); siblingExecution.CurrentFlowElement = miRootExecutionEntity.CurrentFlowElement; DeleteExecutionEntities(executionEntityManager, miRootExecutionEntity, CreateDeleteReason(miRootExecutionEntity.ActivityId)); Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(siblingExecution, true); } else { DefaultTerminateEndEventBehaviour(execution, commandContext, executionEntityManager); } }
public override void Trigger(IExecutionEntity execution, string triggerName, object triggerData, bool throwError = true) { ICommandContext commandContext = Context.CommandContext; IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager; StartEvent startEvent = (StartEvent)execution.CurrentFlowElement; if (startEvent.Interrupting) { IList <IExecutionEntity> childExecutions = executionEntityManager.FindChildExecutionsByParentExecutionId(execution.ParentId); foreach (IExecutionEntity childExecution in childExecutions) { if (!childExecution.Id.Equals(execution.Id)) { executionEntityManager.DeleteExecutionAndRelatedData(childExecution, History.DeleteReasonFields.EVENT_SUBPROCESS_INTERRUPTING + "(" + startEvent.Id + ")", false); } } } IEventSubscriptionEntityManager eventSubscriptionEntityManager = Context.CommandContext.EventSubscriptionEntityManager; IList <IEventSubscriptionEntity> eventSubscriptions = execution.EventSubscriptions; foreach (IEventSubscriptionEntity eventSubscription in eventSubscriptions) { if (eventSubscription.EventType == MessageEventSubscriptionEntityFields.EVENT_TYPE && eventSubscription.EventName.Equals(messageEventDefinition.MessageRef)) { eventSubscriptionEntityManager.Delete(eventSubscription); } } execution.CurrentFlowElement = (SubProcess)execution.CurrentFlowElement.ParentContainer; execution.IsScope = true; IExecutionEntity outgoingFlowExecution = executionEntityManager.CreateChildExecution(execution); outgoingFlowExecution.CurrentFlowElement = startEvent; Leave(outgoingFlowExecution); }
public virtual object Execute(ICommandContext commandContext) { lock (syncRoot) { ProcessEngineConfigurationImpl processEngineConfiguration = commandContext.ProcessEngineConfiguration; Interceptor.ICommandExecutor commandExecutor = processEngineConfiguration.CommandExecutor; ITaskEntity task = commandExecutor.Execute(new GetTaskByIdCmd(currentTaskId)) as ITaskEntity; if (task is null) { throw new ActivitiObjectNotFoundException(string.Concat("No task found for id '", currentTaskId)); } string currentExecutionId = task.ExecutionId; IExecutionEntity execution = task.Execution; if (execution is null) { throw new ActivitiObjectNotFoundException(string.Concat("No execution found for id '", currentExecutionId)); } var flowElement = ProcessDefinitionUtil.GetFlowElement(execution.ProcessDefinitionId, returnToActivityId); if (flowElement is null) { throw new ActivitiObjectNotFoundException(string.Concat("No execution found for id '", currentExecutionId, "'")); } IHistoricActivityInstanceEntity hisInst = processEngineConfiguration.HistoryService.CreateHistoricActivityInstanceQuery() .SetProcessInstanceId(execution.ProcessInstanceId) .SetActivityId(returnToActivityId) .OrderByHistoricActivityInstanceStartTime() .Desc() .List() .FirstOrDefault() as IHistoricActivityInstanceEntity; IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager; IExecutionEntity returnToExec = executionEntityManager.CreateChildExecution(execution.ProcessInstance); returnToExec.CurrentFlowElement = flowElement; foreach (var key in variables.Keys) { returnToExec.SetVariable(key, variables[key]); } executionEntityManager.Insert(returnToExec); commandContext.Agenda.PlanContinueProcessOperation(returnToExec); IExecutionEntity miRoot = commandExecutor.Execute(new GetMultiInstanceRootExecutionCmd(execution)); List <ITask> tasks = new List <ITask>(); if (miRoot != null) { ITaskQuery query = commandContext.ProcessEngineConfiguration.TaskService.CreateTaskQuery(); IEnumerable <IExecutionEntity> childExecutions = commandExecutor.Execute(new GetChildExecutionsCmd(miRoot)); query.SetExecutionIdIn(childExecutions.Select(x => x.Id).ToArray()); tasks.AddRange(query.List()); } else { tasks.Add(task); } DeleteTasks(commandContext, commandExecutor, miRoot != null ? miRoot : execution, executionEntityManager, tasks); return(null); } }
public override void Execute(IExecutionEntity execution) { string finalProcessDefinitonKey; if (processDefinitionExpression != null) { finalProcessDefinitonKey = (string)processDefinitionExpression.GetValue(execution); } else { finalProcessDefinitonKey = processDefinitonKey; } IProcessDefinition processDefinition = FindProcessDefinition(finalProcessDefinitonKey, execution.TenantId); // Get model from cache Process subProcess = ProcessDefinitionUtil.GetProcess(processDefinition.Id); if (subProcess == null) { throw new ActivitiException("Cannot start a sub process instance. Process model " + processDefinition.Name + " (id = " + processDefinition.Id + ") could not be found"); } FlowElement initialFlowElement = subProcess.InitialFlowElement; if (initialFlowElement == null) { throw new ActivitiException("No start element found for process definition " + processDefinition.Id); } // Do not start a process instance if the process definition is suspended if (ProcessDefinitionUtil.IsProcessDefinitionSuspended(processDefinition.Id)) { throw new ActivitiException("Cannot start process instance. Process definition " + processDefinition.Name + " (id = " + processDefinition.Id + ") is suspended"); } ProcessEngineConfigurationImpl processEngineConfiguration = Context.ProcessEngineConfiguration; IExecutionEntityManager executionEntityManager = Context.CommandContext.ExecutionEntityManager; ExpressionManager expressionManager = processEngineConfiguration.ExpressionManager; CallActivity callActivity = (CallActivity)execution.CurrentFlowElement; string businessKey = null; if (!string.IsNullOrWhiteSpace(callActivity.BusinessKey)) { IExpression expression = expressionManager.CreateExpression(callActivity.BusinessKey); businessKey = expression.GetValue(execution).ToString(); } else if (callActivity.InheritBusinessKey) { IExecutionEntity processInstance = executionEntityManager.FindById <IExecutionEntity>(execution.ProcessInstanceId); businessKey = processInstance.BusinessKey; } IExecutionEntity subProcessInstance = Context.CommandContext.ExecutionEntityManager.CreateSubprocessInstance(processDefinition, execution, businessKey); Context.CommandContext.HistoryManager.RecordSubProcessInstanceStart(execution, subProcessInstance, initialFlowElement); // process template-defined data objects IDictionary <string, object> variables = ProcessDataObjects(subProcess.DataObjects); if (callActivity.InheritVariables) { IDictionary <string, object> executionVariables = execution.Variables; foreach (KeyValuePair <string, object> entry in executionVariables.SetOfKeyValuePairs()) { variables[entry.Key] = entry.Value; } } // copy process variables foreach (IOParameter ioParameter in callActivity.InParameters) { object value = null; if (!string.IsNullOrWhiteSpace(ioParameter.SourceExpression)) { IExpression expression = expressionManager.CreateExpression(ioParameter.SourceExpression.Trim()); value = expression.GetValue(execution); } else { value = execution.GetVariable(ioParameter.Source); } variables[ioParameter.Target] = value; } if (variables.Count > 0) { InitializeVariables(subProcessInstance, variables); } // Create the first execution that will visit all the process definition elements IExecutionEntity subProcessInitialExecution = executionEntityManager.CreateChildExecution(subProcessInstance); subProcessInitialExecution.CurrentFlowElement = initialFlowElement; Context.Agenda.PlanContinueProcessOperation(subProcessInitialExecution); Context.ProcessEngineConfiguration.EventDispatcher.DispatchEvent(ActivitiEventBuilder.CreateProcessStartedEvent(subProcessInitialExecution, variables, false)); }