Activiti 5.0 回退到任意节点(并行)
应用场景
针对activiti实现平行网关回退
解决方案
任意节点回退思路
- 获取回退节点id,获取当前任务id
- 保存当前任务节点id流向
- 清除当前任务节点id流向
- 将当前任务节点任务流向退回节点id
- 完成当前节点任务
- 恢复当前节点流向
针对并行网关
处于并行网关内回退至网关外节点(如2.1回退到1),需考虑2.2是否已经完成,若已完成则不用管,若未完成,则需将2.2任务删除,否则会出现两个单
处于并行网关外回退至网关内节点(如3回退到2.1),需将2.2也回退,不然2.1通过后3不会创建新任务
核心代码
@Transactional(rollbackFor = Exception.class) public String backToAnyActivity(String taskId, String backToActivityId, String comment, Map<String, Object> variables) { if (this.isMultiInstance(taskId)) { throw new RenException(ErrorCode.REJECT_PROCESS_PARALLEL_ERROR); } // 用于保存历史审批人 Map<String, String> historicAssigneeMap = new HashMap<>(); HistoricTaskInstance currTask = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult(); ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(currTask.getProcessInstanceId()).singleResult(); ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService) .getDeployedProcessDefinition(currTask.getProcessDefinitionId()); if (processDefinitionEntity == null) { throw new RenException(ErrorCode.NONE_EXIST_PROCESS); } this.taskService.setVariablesLocal(taskId, variables); List<HistoricActivityInstance> backHistoricActivityInstances = historyService .createHistoricActivityInstanceQuery().activityType("userTask") .processInstanceId(processInstance.getId()) .finished() .activityId(backToActivityId).list(); if (backHistoricActivityInstances == null || backHistoricActivityInstances.isEmpty()) { throw new RuntimeException("不存在activity:" + backToActivityId); } List<Task> tasks = taskService.createTaskQuery().processInstanceId(currTask.getProcessInstanceId()) .taskDefinitionKey(currTask.getTaskDefinitionKey()).list(); if (tasks.size() > 1) { throw new RenException(ErrorCode.REJECT_PROCESS_HANDLEING_ERROR); } ActivityImpl currActivity = processDefinitionEntity.findActivity(currTask.getTaskDefinitionKey()); //判断是否要删除任务,默认不删除 Boolean isDeleteTask = false; // 判断回退任务是否在并行任务中 List<ActivityImpl> canBackActivitys = this.getCanBackUpActivityByParallelGateway(backToActivityId, processDefinitionEntity); if (canBackActivitys.size() == 0) { canBackActivitys = this.deleteCanBackUpActivityByParallelGateway(backToActivityId, processDefinitionEntity, currTask); isDeleteTask = true; } List<PvmTransition> originPvmTransitionList = new ArrayList<>(); List<PvmTransition> pvmTransitionList = currActivity.getOutgoingTransitions(); for (PvmTransition pvmTransition : pvmTransitionList) { originPvmTransitionList.add(pvmTransition); } pvmTransitionList.clear(); List<HistoricActivityInstance> historicActivityInstances = historyService .createHistoricActivityInstanceQuery().activityType("userTask") .processInstanceId(processInstance.getId()) .finished().orderByHistoricActivityInstanceEndTime().asc().list(); // 获取历史审批人 for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) { historicAssigneeMap.put(historicActivityInstance.getActivityId(), historicActivityInstance.getAssignee()); } List<TransitionImpl> transitions = new ArrayList<>(); // 退回任务 if (historicActivityInstances.size() > 0) { ActivityImpl lastActivity = processDefinitionEntity.findActivity(backToActivityId); TransitionImpl transitionImpl = currActivity.createOutgoingTransition(); transitionImpl.setDestination(lastActivity); transitions.add(transitionImpl); } else { throw new RenException(ErrorCode.SUPERIOR_NOT_EXIST); } List<String> ids = new ArrayList<>(); // 若为并行任务,将另一个任务也退回 for (ActivityImpl canBackActivity : canBackActivitys) { if (!canBackActivity.getId().equals(backToActivityId)) { ActivityImpl otherActivity = processDefinitionEntity.findActivity(canBackActivity.getId()); TransitionImpl transitionImpl = currActivity.createOutgoingTransition(); transitionImpl.setDestination(otherActivity); transitions.add(transitionImpl); // 用于同意任务 ids.add(canBackActivity.getId()); } } if (variables == null) { variables = processInstance.getProcessVariables(); } for (Task task : tasks) { String commentMode = MessageUtils.getMessage(ErrorCode.ROLLBACK_MESSAGE); if (StringUtils.isNotEmpty(comment)) { commentMode += "[" + comment + "]"; } // 清空之前保存的评论 List<Comment> comments = taskService.getTaskComments(task.getId(), "comment"); for (Comment com : comments) { taskService.deleteComment(com.getId()); } taskService.addComment(task.getId(), task.getProcessInstanceId(), commentMode); taskService.complete(task.getId(), variables); } for (TransitionImpl transition : transitions) { currActivity.getOutgoingTransitions().remove(transition); } for (PvmTransition pvmTransition : originPvmTransitionList) { pvmTransitionList.add(pvmTransition); } //返回回退之后的任务id Task task = taskService.createTaskQuery() .processInstanceId(currTask.getProcessInstanceId()) .processDefinitionId(currTask.getProcessDefinitionId()) .taskDefinitionKey(backToActivityId) .singleResult(); String assignee = historicAssigneeMap.get(backToActivityId); if (!"".equals(assignee) && assignee != null) { taskService.setAssignee(task.getId(), assignee); } // 将其余并行任务结束 for (String id : ids) { if (isDeleteTask) { List<Task> deleteTaskList = taskService.createTaskQuery() .processInstanceId(currTask.getProcessInstanceId()) .processDefinitionId(currTask.getProcessDefinitionId()) .taskDefinitionKey(id) .list(); //删除任务 for (Task deleteTask : deleteTaskList) { //删除ru Execution 和 ru task 表字段 } } else { if ((!id.equals(backToActivityId))) { Task otherTask = taskService.createTaskQuery() .processInstanceId(currTask.getProcessInstanceId()) .processDefinitionId(currTask.getProcessDefinitionId()) .taskDefinitionKey(id) .singleResult(); if (otherTask == null){ continue; } String otherAssignee = historicAssigneeMap.get(id); String otherTaskId = otherTask.getId(); taskService.addComment(otherTaskId, otherTask.getProcessInstanceId(), "[网关回退自动提交]"); taskService.setAssignee(otherTaskId, otherAssignee); taskService.complete(otherTaskId); } } } return task.getId(); }
/**
* 结束节点回退到并行网关内部节点
*
* @param backToActivityId
* @param processDefinitionEntity
* @return
*/
private List<ActivityImpl> getCanBackUpActivityByParallelGateway(String backToActivityId, ProcessDefinitionEntity processDefinitionEntity) {
List<ActivityImpl> rtnList = new ArrayList<>();
// 获取回退节点
ActivityImpl backActivity = processDefinitionEntity.findActivity(backToActivityId);
// 获取回退节点的下一个节点
List<PvmTransition> outgoingTransitions = backActivity.getOutgoingTransitions();
// 判断下个节点是否为并行网关
for (PvmTransition outgoingTransition : outgoingTransitions) {
TransitionImpl transitionImpl = (TransitionImpl) outgoingTransition;
ActivityImpl activityImpl = transitionImpl.getSource();
String type = (String) activityImpl.getProperty("type");
// 是否有多个出口
if (activityImpl.getOutgoingTransitions().size() > 1) {
return rtnList;
}
if ("parallelGateway".equals(type)) {
// 获取并行网关的所有入口
List<PvmTransition> incomingParallelGateway = activityImpl.getIncomingTransitions();
for (PvmTransition pvmTransition : incomingParallelGateway) {
TransitionImpl transition = (TransitionImpl) pvmTransition;
ActivityImpl activity = transition.getSource();
if ("userTask".equals(activity.getProperty("type"))) {
rtnList.add(activity);
}
}
}
}
return rtnList;
}
/**
* 并行网关内部节点回退到开始节点
*
* @param backToActivityId
* @param processDefinitionEntity
* @param currTask
*/
public List<ActivityImpl> deleteCanBackUpActivityByParallelGateway(String backToActivityId, ProcessDefinitionEntity processDefinitionEntity, HistoricTaskInstance currTask) {
// 获取回退节点
ActivityImpl backActivity = processDefinitionEntity.findActivity(backToActivityId);
//记录activity
List<ActivityImpl> activityImpls = new ArrayList<>();
List<PvmTransition> isParallelGateways = backActivity.getOutgoingTransitions();
for (PvmTransition isParallelGateway : isParallelGateways) {
TransitionImpl isTransitionParallelGateway = (TransitionImpl) isParallelGateway;
ActivityImpl activityImpl = isTransitionParallelGateway.getDestination();
if ("parallelGateway".equals(activityImpl.getProperty("type"))) {
// 获取并行网关下的全部节点
List<PvmTransition> outgoingTransitions = activityImpl.getOutgoingTransitions();
for (PvmTransition outgoingTransition : outgoingTransitions) {
// 转为activityImpl
TransitionImpl transition = (TransitionImpl) outgoingTransition;
ActivityImpl activity = transition.getDestination();
if ("userTask".equals(activity.getProperty("type"))) {
// 并行回退自动
if (!currTask.getTaskDefinitionKey().equals(activity.getId())) {
Task task = taskService.createTaskQuery()
.processInstanceId(currTask.getProcessInstanceId())
.processDefinitionId(currTask.getProcessDefinitionId())
.taskDefinitionKey(activity.getId())
.singleResult();
if (task != null) {
activityImpls.add(activity);
}
}
}
}
}
}
return activityImpls;
}