Activiti6.0 (ten) task handler change (reassignment), free jump (back)

table of Contents

I. Introduction

2. Realization of reassignment

Three, free jump realization

Idea 1

Idea 2


I. Introduction

When the process is circulating, the change of task handler in a certain link (ie reassignment ) is a very common requirement. Originally, the task handler may be A, but because A cannot handle something, the administrator needs to reassign the order to B Under temporary treatment.

In the Chinese-style process, process  rollback  is also indispensable. When the process flows to a certain link, the processor will take a look: Hey, what is filled in, it does not meet the requirements at all, and I want to call it back directly. One link or any link you go through, then you need to support the rollback function; sometimes there are special requirements in the process, such as leapfrog reporting , some handlers have higher authority to run, skip some links and execute directly, or even say yes Step to the end , this depends on the free process of Activiti

This article briefly introduces how to implement reassignment and rollback in Activiti.

 

2. Realization of reassignment

In the actual use of Activiti, most companies have their own user management system, and Activiti's own user and user group functions cannot actually meet some needs, such as assigning to a department, a role, and so on. Therefore, the personnel information in Activiti is actually not that important. In our project, we don't even get personnel information from it, just set values. Activiti's task handlers are mainly stored in the ASSIGNEE_ field of ACT_RU_TASK and ACT_RU_IDENTITYLINK. The former is mainly the case of a single reviewer, and the latter is mainly the case of the candidate.

In fact, the implementation of reassignment is very simple, that is, to reset the handler for the current task, call the following method:

taskService.setAssignee("taskId", "userId");

When the process variable is used to set the processor, there may be multiple processors or processing groups in business, so the user array stored in ASSIGNEE_ may be in the form: [a,b,b]. Since the ASSIGNEE_ field is of varchar type and only 255, if the user id is in uuid format, only 7 can be stored at most...

There are quite a lot of APIs for setting handlers, and there is another way:

taskService.unclaim("taskId");
taskService.claim("taskId", "userId");

The main difference between this method and the above is that the claim method will check whether there is a handler currently, and if there is an error, the unclaim method needs to be called first.

 

Three, free jump realization

The biggest change in Activiti6 is the refactoring of the code. It removes the original pvm and directly deals with bpmn, so the performance will be slightly improved (I haven't tried it. The previous project used Activiti5.22, so the original The implementation of free jump is completely different from the implementation of 6. As a digression, pvm is mainly responsible for all operation operations such as the execution and circulation of the entire runtime of the process. All its implementation classes are in the org.activiti.engine.impl.pvm package. , But all 6 are removed...)

Here we mainly demonstrate the scenario of rollback. First look at the flow chart above. Assuming that the current task has been transferred to the leader for approval, the leader will see that your approval information is incorrectly filled, and you need to reject it. Pop a bit. At this time, the process needs to be rolled back. How to complete the process of filling in the approval information?

Idea 1

During the running process, dynamically modify the process definition of Activiti, modify the exit line of the leader approval link, and make it flow to the approval information filling, and then resume the original exit line of the leader approval (that is, the end link) after the transfer is completed. This method can also be realized. Jump freely, but there is a problem of concurrency. Assuming that A clicks back, the process definition has been modified at this time, and the lead approval line has become the approval information filling, and B clicks submit, but found that the process flow goes to the approval information filling... .B said it was a ghost. So undesirable

Idea 2

Use the execution plan to directly specify the current process instance to execute the selected link. Because the execution id of the current task is unique in the case of concurrency, this method does not bring insecurity. The following code is implemented based on this:

The first are two commands, namely delete the current task command and execute the free jump command:

/**
 * 继承NeedsActiveTaskCmd主要是为了在跳转时要求当前任务不能是挂起状态,也可以直接实现Command接口
 * Created by xujia on 2020/2/10
 */
public class DeleteTaskCmd extends NeedsActiveTaskCmd<String> {

    public DeleteTaskCmd(String taskId){
        super(taskId);
    }

    public String execute(CommandContext commandContext, TaskEntity currentTask){
        TaskEntityManagerImpl taskEntityManager = (TaskEntityManagerImpl)commandContext.getTaskEntityManager();
        // 获取当前任务的执行对象实例
        ExecutionEntity executionEntity = currentTask.getExecution();
        // 删除当前任务,来源任务
        taskEntityManager.deleteTask(currentTask, "jumpReason", false, false);
        // 返回当前任务的执行对象id
        return executionEntity.getId();
    }
    public String getSuspendedTaskException() {
        return "挂起的任务不能跳转";
    }
}

/**
 * 执行自由跳转命令
 * Created by xujia on 2020/2/10
 */
public class SetFLowNodeAndGoCmd implements Command<Void> {

    /**
     * 目标节点对象
     */
    private FlowNode flowElement;
    /**
     * 当前任务执行id
     */
    private String executionId;

    public SetFLowNodeAndGoCmd(FlowNode flowElement,String executionId){
        this.flowElement = flowElement;
        this.executionId = executionId;
    }

    public Void execute(CommandContext commandContext){
        // 获取目标节点的来源连线
        List<SequenceFlow> flows = flowElement.getIncomingFlows();
        if(flows==null || flows.size()<1){
            throw new ActivitiException("回退错误,目标节点没有来源连线");
        }
        // 随便选一条目标节点的入线来执行,使当前执行计划为:从所选择的流程线流转到目标节点,实现跳转
        ExecutionEntity executionEntity = commandContext.getExecutionEntityManager().findById(executionId);
        executionEntity.setCurrentFlowElement(flows.get(0));
        commandContext.getAgenda().planTakeOutgoingSequenceFlowsOperation(executionEntity, true);
        return null;
    }
}

Then call:

@Test
    public void listTaskTest() {
        // 获取当前任务
        Task currentTask = taskService.createTaskQuery().taskId("132502").singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId());
        // 获取流程定义
        Process process = bpmnModel.getMainProcess();
        // 获取目标节点定义
        FlowNode targetNode = (FlowNode) process.getFlowElement("sid-C24BA4F5-F744-4DD7-8D51-03C3698044D2");

        // 删除当前运行任务,同时返回执行id,该id在并发情况下也是唯一的
        String executionEntityId = managementService.executeCommand(new DeleteTaskCmd(currentTask.getId()));
        // 流程执行到来源节点
        managementService.executeCommand(new SetFLowNodeAndGoCmd(targetNode, executionEntityId));
    }

After running, you will find that the process flows directly to the approval information filling link, and the processor has become the original processor, and flexible use can achieve a variety of needs.

Guess you like

Origin blog.csdn.net/m0_38001814/article/details/104253357