Activiti 5.0 回退到任意节点(2)

应用场景

​ 针对activiti中国式需求,实现平行网关回退,部分代码上文有说道,但是上文有个bug(后文称为旧版),就是回退会推进进程,何为推进进程看图
在这里插入图片描述
如果使用上文的方法,在c2已经执行完的情况下,b2进行回退给b1,就会出现两个任务同时存在的情况下
原因是因为,在act_ru_execution表有记录并行的任务,当b2和c2完成任务后将推进

在这里插入图片描述
这显然是不符合预期的,所以本篇为了解决这个问题,采用了新的回退方式
我把这种方式叫任务跳转

解决思路

activiti在每个正在执行的任务都有一个执行器,即ru_task表(数据表act_ru_task,后面介绍到数据表会省略act_)的数据会与ru_execution有相对应的关系,当前的跳转实现就用到这个执行器,俗话说就是鸠占鹊巢的方法

  1. 获取当前任务id,获取需要跳转节点id
  2. 根据任务id获取当前任务对象
  3. 根据跳转节点id获取节点对象,即(ActivityImpl)
  4. 创建新的工作流任务,节点使用的是步骤3获取的节点,执行器id使用的是步骤2执行器id
  5. 删除步骤2的任务已经相关联的数据

与旧版对比

旧版:使用改变节点的去向,然后使用taskService.complete的方法将任务强行回退给指定的节点,然后在恢复节点的去向,这种的如果用在非并行流程其实是没问题的。

新版:使用跳转的方式,不会推动进程,改变的最少,需要删除比较多的数据

核心代码

只展示部分核心代码,完整代码涉及一些隐私,请见谅

创建新的工作流任务代码

import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.runtime.AtomicOperation;

public class CreateActivityCmd implements Command<Void> {

    private ActivityImpl _activity;

    private String _executionId;

    public CreateActivityCmd(String executionId, ActivityImpl activity) {
        _activity = activity;
        _executionId = executionId;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        //创建新任务
        ExecutionEntity execution = commandContext.getExecutionEntityManager().findExecutionById(_executionId);
        execution.setActivity(_activity);

        execution.performOperation(AtomicOperation.ACTIVITY_START);
        return null;
    }

}

跳转代码

@Transactional(rollbackFor = Exception.class)
    public void backToAnyTask(String taskId, String backToActivityId, String comment, Map<String, Object> variables, Integer backFlag) {
    	// 判断是否为多实例任务
        if (this.isMultiInstance(taskId)) {
            throw new RenException(ErrorCode.REJECT_PROCESS_PARALLEL_ERROR);
        }
        //创建managementService
        ManagementService managementService = ProcessEngines.getDefaultProcessEngine().getManagementService();
        //    获取当前任务
        TaskEntity currTask = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
        ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                .getDeployedProcessDefinition(currTask.getProcessDefinitionId());
        if (processDefinitionEntity == null) {
            throw new RenException(ErrorCode.NONE_EXIST_PROCESS);
        }

        List<HistoricActivityInstance> backHistoricActivityInstances = historyService
                .createHistoricActivityInstanceQuery().activityType("userTask")
                .processInstanceId(currTask.getProcessInstanceId())
                .finished()
                .activityId(backToActivityId).list();
        if (backHistoricActivityInstances == null || backHistoricActivityInstances.isEmpty()) {
            throw new RuntimeException("不存在activity:" + backToActivityId);
        }
        //退回活动节点
        ActivityImpl backActivity = processDefinitionEntity.findActivity(backToActivityId);

        //    并行任务额外操作
        //判断是否要删除任务,默认不删除
        Boolean isDeleteTask = false;
        //用于保存需要删除的执行器的任务
        //        判断回退任务是否在并行任务中
        List<ActivityImpl> canBackActivitys = new ArrayList<>();
        // 如果没有并行网关不用递归
        if (modelNodeService.isParallelGatewayInModel(currTask.getProcessDefinitionId())){
            this.endActivityCanBackListByParallelGateway(currTask.getTaskDefinitionKey(), processDefinitionEntity, canBackActivitys, backToActivityId);
        }
        if (canBackActivitys.isEmpty()) {
            //    通过historyService获取当前任务
            HistoricTaskInstance historicCurrTask = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
            this.deleteCanBackActivityByParallelGateway(backToActivityId, processDefinitionEntity, historicCurrTask, canBackActivitys);
            isDeleteTask = true;
        } 
        //退回节点的历史任务
        List<HistoricTaskInstance> hisTasks = historyService.createHistoricTaskInstanceQuery()
                .taskDefinitionKey(backToActivityId)
                .processDefinitionId(currTask.getProcessDefinitionId())
                .processInstanceId(currTask.getProcessInstanceId())
                .orderByHistoricTaskInstanceEndTime().desc()
                .list();
        //查找并行网关的结束并行网关,并删除执行器
        if (isDeleteTask && canBackActivitys.isEmpty() && backFlag != 0) {
            this.getParallelGatewayOrderActivity(processDefinitionEntity.findActivity(currTask.getTaskDefinitionKey()),currTask.getProcessInstanceId());
        }
        //    指向命令进行回退
        //创建新工作流任务
        managementService.executeCommand(new CreateActivityCmd(currTask.getExecutionId(), backActivity));
        //最后再删除原来的任务
        this.deleteTask(currTask.getId(), currTask.getExecutionId());
        //回退后新任务
        Task newTask = taskService.createTaskQuery()
                .processInstanceId(currTask.getProcessInstanceId())
                .processDefinitionId(currTask.getProcessDefinitionId())
                .taskDefinitionKey(backToActivityId)
                .singleResult();
        taskService.setVariablesLocal(newTask.getId(), variables);
        String thisAssigness = "";
        for (HistoricTaskInstance hisTask : hisTasks) {
            if (!"".equals(hisTask.getAssignee()) && hisTask.getAssignee() != null) {
                thisAssigness = hisTask.getAssignee();
                break;
            }
        }
        //设置审批人
        taskService.setAssignee(newTask.getId(), thisAssigness);
        if ( !BACK_FLAG.equals(backFlag)) {
            //处理并行回退操作
            for (ActivityImpl canBackActivity : canBackActivitys) {
                if (isDeleteTask) {
                    //    并行内部回退至外部需要删除任务
                    List<Task> deleteTaskList = taskService.createTaskQuery()
                            .processInstanceId(currTask.getProcessInstanceId())
                            .processDefinitionId(currTask.getProcessDefinitionId())
                            .taskDefinitionKey(canBackActivity.getId())
                            .list();
                    //删除任务
                    for (Task deleteTask : deleteTaskList) {
                    	// 包括执行器之类的
                        this.deleteTaskAll(deleteTask.getId(), deleteTask.getExecutionId());
                    }

                }
            }
            //    删除回退节点后面的所有节点
            this.deleteAllActivityAfterBackActivity(backActivity, currTask.getProcessInstanceId(), currTask.getProcessDefinitionId());
        }
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值