持续创作,加速成长!这是我参与「掘金日新计划 · 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,但是需要做一些条件判断及相应的数据处理,当上个环节如果是并行流则需要增加额外判断。