Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        /// <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);
        }
Ejemplo n.º 4
0
        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);
                }
            }
        }
Ejemplo n.º 6
0
        /// <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);
        }
Ejemplo n.º 7
0
        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);
            }
        }
Ejemplo n.º 8
0
        /// <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);
        }
Ejemplo n.º 11
0
        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);
            }
        }
Ejemplo n.º 12
0
        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));
        }