activiti学习(二十一)——流程虚拟机源码分析(三)——从进入到离开userTask
前言承接上文《activiti学习(二十)——流程虚拟机源码分析(二)——从开始节点离开到下个节点前》,假设execution接下来进入的节点是userTask,本文分析一下进入userTask的准备工作,到执行userTask的行为类,最后客户端调用taskService.complete方法离开userTask的过程。准备工作承接上文,会调用AtomicOperationTransitionC
前言
承接上文《activiti学习(二十)——流程虚拟机源码分析(二)——从开始节点离开到下个节点前》,假设execution接下来进入的节点是userTask,本文分析一下进入userTask的准备工作,到执行userTask的行为类,最后客户端调用taskService.complete方法离开userTask的过程。
准备工作
承接上文,会调用AtomicOperationTransitionCreateScope类:
public class AtomicOperationTransitionCreateScope implements AtomicOperation {
//......
public void execute(InterpretableExecution execution) {
InterpretableExecution propagatingExecution = null;
ActivityImpl activity = (ActivityImpl) execution.getActivity();
if (activity.isScope()) {
//......
} else {
propagatingExecution = execution;
}
propagatingExecution.performOperation(AtomicOperation.TRANSITION_NOTIFY_LISTENER_START);
}
}
由于userTask的activityImpl的isScope为false,因此单纯以当前execution调用performOperation(AtomicOperation.TRANSITION_NOTIFY_LISTENER_START)。跟踪AtomicOperationTransitionNotifyListenerStart类:
public class AtomicOperationTransitionNotifyListenerStart extends AbstractEventAtomicOperation {
//......
protected String getEventName() {
return org.activiti.engine.impl.pvm.PvmEvent.EVENTNAME_START;
}
protected void eventNotificationsCompleted(InterpretableExecution execution) {
TransitionImpl transition = execution.getTransition();
ActivityImpl destination = null;
if(transition == null) { // this is null after async cont. -> transition is not stored in execution
destination = (ActivityImpl) execution.getActivity();
} else {
destination = transition.getDestination();
}
ActivityImpl activity = (ActivityImpl) execution.getActivity();
if (activity!=destination) {
ActivityImpl nextScope = AtomicOperationTransitionNotifyListenerTake.findNextScope(activity, destination);
execution.setActivity(nextScope);
execution.performOperation(TRANSITION_CREATE_SCOPE);
} else {
execution.setTransition(null);
execution.setActivity(destination);
execution.performOperation(ACTIVITY_EXECUTE);
}
}
}
首先execution的performOperation调用会触发执行监听器获取AtomicOperationTransitionNotifyListenerStart的getEventName对应的事件,这里是start事件,然后触发执行监听器的start事件。不记得performOperation调用逻辑的可回顾《activiti学习(十九)——流程虚拟机源码分析(一)——流程启动源码分析》“流程实例启动”的小节。第10行获取execution当前的连线,此时连线非空,且destination就是当前的ActivityImpl,回顾上文《activiti学习(二十)——流程虚拟机源码分析(二)——从开始节点离开到下个节点前》可知我们刚刚就是从这条连线过来,并且未作变更。因此18行判断为false,执行23-25行代码,23行设置execution当前连线为null,24行设置当前活动为连线终点的活动,按本文的假设,即userTask,25行调用execution.performOperation(ACTIVITY_EXECUTE)。回顾《activiti学习(十九)》可知该原子操作触发全局事件转发器的ACTIVITY_STARTED事件,然后调用当前活动的行为类,这里会调用userTask的行为类UserTaskActivityBehavior。
userTask行为类
进入userTask行为类
public void execute(ActivityExecution execution) throws Exception {
TaskEntity task = TaskEntity.createAndInsert(execution);
task.setExecution(execution);
Expression activeNameExpression = null;
Expression activeDescriptionExpression = null;
Expression activeDueDateExpression = null;
Expression activePriorityExpression = null;
Expression activeCategoryExpression = null;
Expression activeFormKeyExpression = null;
Expression activeSkipExpression = null;
Expression activeAssigneeExpression = null;
Expression activeOwnerExpression = null;
Set<Expression> activeCandidateUserExpressions = null;
Set<Expression> activeCandidateGroupExpressions = null;
if (Context.getProcessEngineConfiguration().isEnableProcessDefinitionInfoCache()) {
//......
} else {
activeNameExpression = taskDefinition.getNameExpression();
activeDescriptionExpression = taskDefinition.getDescriptionExpression();
activeDueDateExpression = taskDefinition.getDueDateExpression();
activePriorityExpression = taskDefinition.getPriorityExpression();
activeCategoryExpression = taskDefinition.getCategoryExpression();
activeFormKeyExpression = taskDefinition.getFormKeyExpression();
activeSkipExpression = taskDefinition.getSkipExpression();
activeAssigneeExpression = taskDefinition.getAssigneeExpression();
activeOwnerExpression = taskDefinition.getOwnerExpression();
activeCandidateUserExpressions = taskDefinition.getCandidateUserIdExpressions();
activeCandidateGroupExpressions = taskDefinition.getCandidateGroupIdExpressions();
}
task.setTaskDefinition(taskDefinition);
//......task属性设置
boolean skipUserTask = SkipExpressionUtil.isSkipExpressionEnabled(execution, activeSkipExpression) &&
SkipExpressionUtil.shouldSkipFlowElement(execution, activeSkipExpression);
if (!skipUserTask) {
handleAssignments(activeAssigneeExpression, activeOwnerExpression, activeCandidateUserExpressions,
activeCandidateGroupExpressions, task, execution);
}
task.fireEvent(TaskListener.EVENTNAME_CREATE);
if (Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createEntityEvent(ActivitiEventType.TASK_CREATED, task));
}
if (skipUserTask) {
task.complete(null, false);
}
}
第2行创建task实体类并放入缓存中,17行判断是否有开启流程定义节点缓存,若没有则执行20-30行单纯获取对象解析时节点的属性。35行省略把获取的节点属性设置到task实体中。37行获取是否满足跳过任务的表达式,如果不满足,则40行执行assignee、candidateGroup、candidateUser等属性的设置,并且触发任务监听器的assignment事件。45行触发任务监听器的create事件。47-50行触发全局事件转发器的TASK_CREATED事件。52行判断若满足跳过任务条件,则直接执行task的complete方法完成任务。至此,流程虚拟机完成了《activiti学习(十九)》中执行StartProcessInstanceCmd命令并返回。所有插入缓存的实体例如ExecutionEntity和TaskEntity等被刷新到数据库中。
离开userTask
通常用户是通过调用TaskService.complete方法提交一个userTask,接下来我们跟踪代码是怎么提交并离开userTask。TaskService.complete方法会调用CompleteTaskCmd命令,我们跟踪CompleteTaskCmd类:
public class CompleteTaskCmd extends NeedsActiveTaskCmd<Void> {
//......
protected Void execute(CommandContext commandContext, TaskEntity task) {
if (variables!=null) {
if (localScope) {
task.setVariablesLocal(variables);
} else if (task.getExecutionId() != null) {
task.setExecutionVariables(variables);
} else {
task.setVariables(variables);
}
}
task.complete(variables, localScope);
return null;
}
//......
}
16行调用taskEntity的complete方法,我们接着跟踪TaskEntity类:
public class TaskEntity extends VariableScopeImpl implements Task, DelegateTask, Serializable, PersistentObject, HasRevision, BulkDeleteable {
//......
public void complete(Map variablesMap, boolean localScope) {
if (getDelegationState() != null && getDelegationState().equals(DelegationState.PENDING)) {
throw new ActivitiException("A delegated task cannot be completed, but should be resolved instead.");
}
fireEvent(TaskListener.EVENTNAME_COMPLETE);
if (Authentication.getAuthenticatedUserId() != null && processInstanceId != null) {
getProcessInstance().involveUser(Authentication.getAuthenticatedUserId(), IdentityLinkType.PARTICIPANT);
}
if(Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createEntityWithVariablesEvent(ActivitiEventType.TASK_COMPLETED, this, variablesMap, localScope));
}
Context
.getCommandContext()
.getTaskEntityManager()
.deleteTask(this, TaskEntity.DELETE_REASON_COMPLETED, false);
if (executionId!=null) {
ExecutionEntity execution = getExecution();
execution.removeTask(this);
execution.signal(null, null);
}
}
//......
}
11行触发任务监听器complete事件。13-15行设置IdentityLinkEntity,对应act_ru_identityLink表,注意在上一小节handleAssignments函数时,也会调用类似的函数,把assignee设置到IdentityLinkEntity中,这里会检查如果有相同的userId则返回而不会重复插入。17-20行触发全局事件转发器的TASK_COMPLETED事件。22-25行删除task。30行调用execution.signal,我们跟踪ExecutionEntity类:
public class ExecutionEntity extends VariableScopeImpl implements ActivityExecution, ExecutionListenerExecution, Execution, PvmExecution,
ProcessInstance, InterpretableExecution, PersistentObject, HasRevision {
//......
public void signal(String signalName, Object signalData) {
ensureActivityInitialized();
SignallableActivityBehavior activityBehavior = (SignallableActivityBehavior) activity.getActivityBehavior();
try {
String signalledActivityId = activity.getId();
activityBehavior.signal(this, signalName, signalData);
// If needed, dispatch an event indicating an activity was signalled
boolean isUserTask = (activityBehavior instanceof UserTaskActivityBehavior)
|| ((activityBehavior instanceof MultiInstanceActivityBehavior)
&& ((MultiInstanceActivityBehavior) activityBehavior).getInnerActivityBehavior() instanceof UserTaskActivityBehavior);
if(!isUserTask && Context.getProcessEngineConfiguration() != null
&& Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(ActivitiEventBuilder.createSignalEvent(
ActivitiEventType.ACTIVITY_SIGNALED, signalledActivityId, signalName, signalData, this.id, this.processInstanceId, this.processDefinitionId));
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new PvmException("couldn't process signal '"+signalName+"' on activity '"+activity.getId()+"': "+e.getMessage(), e);
}
}
//......
}
第7行确保execution当前的活动不为空。第8行获取当前活动的行为类。11行调用行为类的signal方法。14行获取isUserTask是非值,这里显然activityBehavior就是UserTaskActivityBehavior,因此为true,所以不会执行18-22行的事件转发。我们跟踪UserTaskActivityBehavior的signal方法:
public class UserTaskActivityBehavior extends TaskActivityBehavior {
//......
public void signal(ActivityExecution execution, String signalName, Object signalData) throws Exception {
if (!((ExecutionEntity) execution).getTasks().isEmpty())
throw new ActivitiException("UserTask should not be signalled before complete");
leave(execution);
}
//......
}
signal方法调用leave离开userTask,这里调用AbstractBpmnActivityBehavior的leave方法,跟踪AbstractBpmnActivityBehavior类:
public class AbstractBpmnActivityBehavior extends FlowNodeActivityBehavior {
//......
protected void leave(ActivityExecution execution) {
if(hasCompensationHandler(execution)) {
createCompensateEventSubscription(execution);
}
if (!hasLoopCharacteristics()) {
super.leave(execution);
} else if (hasMultiInstanceCharacteristics()){
multiInstanceActivityBehavior.leave(execution);
}
}
//......
}
第6行判断userTask是否设置isForCompensation, userTask默认不设置,这里先不细述。第9行判断是否为多实例任务,这里我们假设userTask不是多实例任务,则走第10行,调用FlowNodeActivityBehavior的leave:
public abstract class FlowNodeActivityBehavior implements SignallableActivityBehavior {
//......
protected void leave(ActivityExecution execution) {
bpmnActivityBehavior.performDefaultOutgoingBehavior(execution);
}
//......
}
这里只是简单调用BpmnActivityBehavior的performDefaultOutgoingBehavior方法,跟踪BpmnActivityBehavior:
public class BpmnActivityBehavior implements Serializable {
//......
public void performDefaultOutgoingBehavior(ActivityExecution activityExecution) {
ActivityImpl activity = (ActivityImpl) activityExecution.getActivity();
if (!(activity.getActivityBehavior() instanceof IntermediateCatchEventActivityBehavior)) {
dispatchJobCanceledEvents(activityExecution);
}
performOutgoingBehavior(activityExecution, true, false, null);
}
protected void performOutgoingBehavior(ActivityExecution execution,
boolean checkConditions, boolean throwExceptionIfExecutionStuck, List<ActivityExecution> reusableExecutions) {
//......
String defaultSequenceFlow = (String) execution.getActivity().getProperty("default");
List<PvmTransition> transitionsToTake = new ArrayList<PvmTransition>();
List<PvmTransition> outgoingTransitions = execution.getActivity().getOutgoingTransitions();
for (PvmTransition outgoingTransition : outgoingTransitions) {
Expression skipExpression = outgoingTransition.getSkipExpression();
if (!SkipExpressionUtil.isSkipExpressionEnabled(execution, skipExpression)) {
if (defaultSequenceFlow == null || !outgoingTransition.getId().equals(defaultSequenceFlow)) {
Condition condition = (Condition) outgoingTransition.getProperty(BpmnParse.PROPERTYNAME_CONDITION);
if (condition == null || !checkConditions || condition.evaluate(outgoingTransition.getId(), execution)) {
transitionsToTake.add(outgoingTransition);
}
}
} else if (SkipExpressionUtil.shouldSkipFlowElement(execution, skipExpression)){
transitionsToTake.add(outgoingTransition);
}
}
if (transitionsToTake.size() == 1) {
execution.take(transitionsToTake.get(0));
} else if (transitionsToTake.size() >= 1) {
execution.inactivate();
if (reusableExecutions == null || reusableExecutions.isEmpty()) {
execution.takeAll(transitionsToTake, Arrays.asList(execution));
} else {
execution.takeAll(transitionsToTake, reusableExecutions);
}
} else {
//......
}
}
//......
}
第7行判断为非,直接执行第10行,跳转到13行的函数中。20行获取userTask的“出线”。25-29行判断当满足“出线”条件时,把“出线”加入到待离开的连线集合中。32-34行判断若满足跳过节点条件,也加入待离开的连线集合中。若待离开的连线集合数量是1,则执行38行execution.take离开,否则执行execution.takeAll离开。关于execution的take和takeAll,在《activiti学习(二十)》中分析过,不了解的同学可以去看一下。
小结
本文对于审批流程自由跳转来说是非常重要的预热环节,这里集中了一个普通的用户任务离开时会做什么,进入时会做什么。由于activiti没有提供流程自由跳转的api,我们必须手动去实现这种效果。关于如何实现,留到下一篇文章中再讲。
更多推荐
所有评论(0)