Activiti7 驳回任务

528 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第31天,点击查看活动详情

Activiti7 驳回任务

bpmn正常流程没有驳回/退回,按官方写法应该是通过连接线来实现流程的扭转,但国内的使用习惯并不是完全按照标准规范来,所以才有驳回任务的需求。

下面操作在多分支情况下没有做详细验证,使用请先进行测试.

驳回任务代码

import cn.hutool.core.collection.CollectionUtil;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.delegate.event.ActivitiEventDispatcher;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.impl.ActivitiEventBuilder;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.HistoricTaskInstanceQueryImpl;
import org.activiti.engine.impl.HistoricTaskInstanceQueryProperty;
import org.activiti.engine.impl.cmd.DeleteProcessInstanceCmd;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.identity.Authentication;
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.persistence.entity.HistoricTaskInstanceEntityManager;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.util.ProcessDefinitionUtil;
import org.activiti.engine.task.IdentityLinkType;

import java.util.List;
import java.util.Map;

public class RejectTask implements Command<Void> {

    private String taskId;
    private String rejectReason;
    private Map<String, Object> variables;

    public RejectTask(String taskId, Map<String, Object> variables, String rejectReason) {
        this.taskId = taskId;
        this.variables = variables;
        this.rejectReason = rejectReason;
    }


    @Override
    public Void execute(CommandContext commandContext) {
        // 步骤1
        TaskEntity task = commandContext.getTaskEntityManager().findById(taskId);
        HistoricTaskInstanceEntityManager historicTaskInstanceEntityManager = commandContext.getHistoricTaskInstanceEntityManager();
        HistoricTaskInstanceQueryImpl historicTaskInstanceQuery = new HistoricTaskInstanceQueryImpl();
        historicTaskInstanceQuery.processInstanceId(task.getProcessInstanceId());
        historicTaskInstanceQuery.orderBy(HistoricTaskInstanceQueryProperty.START).desc();
        List<HistoricTaskInstance> htiList = historicTaskInstanceEntityManager.findHistoricTaskInstancesByQueryCriteria(historicTaskInstanceQuery);

        if (CollectionUtil.isEmpty(htiList) || htiList.size() < 2) {
        //步骤2
            DeleteProcessInstanceCmd cmd = new DeleteProcessInstanceCmd(task.getProcessInstanceId(), rejectReason);
            cmd.execute(commandContext);
        } else {
        //步骤3
            // list里的第二条代表上一个任务
            HistoricTaskInstance lastTask = htiList.get(1);
            String processDefinitionId = lastTask.getProcessDefinitionId();
            BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processDefinitionId);

            // 得到上个节点的开始位置
            FlowNode lastFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(lastTask.getTaskDefinitionKey());
            FlowElement begin = lastFlowNode.getIncomingFlows().get(0).getSourceFlowElement();

//步骤4
commandContext.getProcessEngineConfiguration().getListenerNotificationHelper().executeTaskListeners(task, TaskListener.EVENTNAME_COMPLETE);
            if (Authentication.getAuthenticatedUserId() != null && task.getProcessInstanceId() != null) {
                ExecutionEntity processInstanceEntity = commandContext.getExecutionEntityManager().findById(task.getProcessInstanceId());
                commandContext.getIdentityLinkEntityManager().involveUser(processInstanceEntity, Authentication.getAuthenticatedUserId(), IdentityLinkType.PARTICIPANT);
            }

            ActivitiEventDispatcher eventDispatcher = Context.getProcessEngineConfiguration().getEventDispatcher();
            if (eventDispatcher.isEnabled()) {
                eventDispatcher.dispatchEvent(ActivitiEventBuilder.createEntityWithVariablesEvent(ActivitiEventType.TASK_COMPLETED, task, variables, false));
            }
            
            task.setVariables(variables);
            //步骤5
            commandContext.getTaskEntityManager().deleteTask(task, rejectReason, false, false);
            ExecutionEntity executionEntity = commandContext.getExecutionEntityManager().findById(task.getExecutionId());
            executionEntity.setCurrentFlowElement(begin);
            commandContext.getAgenda().planTakeOutgoingSequenceFlowsOperation(executionEntity, true);
        }
        return null;
    }

}

操作说明

  • 步骤1: 获取当前任务,及对应历史记录
  • 步骤2: 如当前任务是第一个任务则删除流程实例
  • 步骤3: 获取上个节点在bpmn模型中位置
  • 步骤4: 完成当前任务并触发相关事件
  • 步骤5: 设置当前执行实例的当前节点,并执行流程引擎计算下一节点.

关键代码为步骤5,但是需要做一些条件判断及相应的数据处理,当上个环节如果是并行流则需要增加额外判断。