前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >activiti多实例节点的任意跳转

activiti多实例节点的任意跳转

作者头像
星痕
发布2018-09-12 11:54:18
2.9K0
发布2018-09-12 11:54:18
举报
文章被收录于专栏:JAVA后端开发JAVA后端开发

activiti是原来不支持节点跳转的,他要求有线才能走,但实际业务中,需要支持动态跳转到各个节点。 一开始,这里的做法是动态构造一条虚拟线的,相关代码如下:

代码语言:javascript
复制
/**
     * 流程转向操作
     * 
     * @param taskId
     *            当前任务ID
     * @param activityId
     *            目标节点任务ID
     * @param variables
     *            流程变量
     * @throws Exception
     */
    public  static void turnTransition(String taskId, String activityId, Map<String, Object> variables)
            throws Exception {
     
        TaskEntity taskEntitiy=findTaskById(taskId);
         
        // 当前节点
        ActivityImpl currActivity = findActivitiImpl(taskId, null);
        // 清空当前流向
        List<PvmTransition> oriPvmTransitionList = clearTransition(currActivity);

        // 创建新流向
        TransitionImpl newTransition = currActivity.createOutgoingTransition();
        // 目标节点
        ActivityImpl pointActivity = findActivitiImpl(taskId, activityId);
        // 设置新流向的目标节点
        newTransition.setDestination(pointActivity);

        // 执行转向任务
        taskService.complete(taskId, variables);
        // 删除目标节点新流入
        pointActivity.getIncomingTransitions().remove(newTransition);

        // 还原以前流向
        restoreTransition(currActivity, oriPvmTransitionList);
    }

这种情况一直好好的,但后续发现流程通过时,自动跳到前面的节点。 经查,原因是这样的: 这种方法可以实现动态跳转,不需要修改Activiti自身执行,但是会动态修改系统中的流程定义缓存对象。理论上这会出现一个多线程下,全局变量不安全的问题。单个Activiti流程引擎中,流程定义缓存对象是被所有线程共用的,当一个应用服务器同时收到两个不同流程实例、同个流程定义、同个环节的任务提交请求。a要求驳回,所以该线程动态修改了流程定义;与此同时,b要求正常流转,但是执行过程中,依据的流程定义已被修改,可能导致b也走向了驳回。 那怎么整,上网查了一下,发现了分享牛的代码,但他的代码存在问题,不支持多实例跳转多实例。 后续将代码修改如下:

代码语言:javascript
复制
package com.meicloud.meiqing.workflow.engine.operation.base;


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

import com.meicloud.meiqing.workflow.engine.constants.CdpActivitiConstant;
import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.impl.ActivitiEventBuilder;
import org.activiti.engine.impl.context.Context;
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.ExecutionEntityManager;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.PvmException;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.ScopeImpl;
import org.activiti.engine.impl.pvm.runtime.AtomicOperation;
import org.activiti.engine.impl.pvm.runtime.InterpretableExecution;

/**
 * @description: 自由跳转流程
 * @author: liumq
 * @create: 2018-06-13 09:22
 **/
public class JDJumpTaskCmd implements Command<Void> {

    protected String taskId;//任务id
    protected String executionId;//执行实例id
    protected String parentId;//流程实例id
    protected ActivityImpl desActivity;//目标节点
    protected Map<String, Object> paramvar;//变量
    protected ActivityImpl currentActivity;//当前的节点

    @Override
    public Void execute(CommandContext commandContext) {

        ExecutionEntityManager executionEntityManager = Context
                .getCommandContext().getExecutionEntityManager();
        ExecutionEntity executionEntity = executionEntityManager
                .findExecutionById(executionId);
        //寻找根路径
        String id = null;
        if (executionEntity.getParent() != null) {
            executionEntity = executionEntity.getParent();

                if (executionEntity.getParent() != null) {
                    executionEntity = executionEntity.getParent();
                    id = executionEntity.getId();
                }

            id = executionEntity.getId();
        }
        //设置相关变量
        executionEntity.setVariables(paramvar);
        //executionEntity.setExecutions(null);
        executionEntity.setEventSource(this.currentActivity);
        executionEntity.setActivity(this.currentActivity);
        // 根据executionId 获取Task
        Iterator<TaskEntity> localIterator = Context.getCommandContext()
                .getTaskEntityManager().findTasksByProcessInstanceId(parentId).iterator();
        //删除无用的工作项
        while (localIterator.hasNext()) {
            TaskEntity taskEntity = (TaskEntity) localIterator.next();
            System.err.println("==================" + taskEntity.getId());
            if(taskId.equals(taskEntity.getId())) {
                // 触发任务监听
                taskEntity.fireEvent("complete");
                // 删除任务的原因
                Context.getCommandContext().getTaskEntityManager()
                        .deleteTask(taskEntity, "completed", false);
            }else {
                // 删除任务的原因
                Context.getCommandContext().getTaskEntityManager()
                        .deleteTask(taskEntity, "deleted", false);
            }

        }
        //删除相关执行子路径,只保留根执行路径
        List<ExecutionEntity> list = executionEntityManager
                .findChildExecutionsByParentExecutionId(parentId);
        for (ExecutionEntity executionEntity2 : list) {
            ExecutionEntity findExecutionById = executionEntityManager.findExecutionById(executionEntity2.getId());

            List<ExecutionEntity> parent = executionEntityManager
                    .findChildExecutionsByParentExecutionId(executionEntity2
                            .getId());
            for (ExecutionEntity executionEntity3 : parent) {
                executionEntity3.remove();
                System.err.println(executionEntity3.getId()
                        + "----------------->>>>>>>>>>");
                Context.getCommandContext().getHistoryManager()
                        .recordActivityEnd(executionEntity3);

            }

                  executionEntity2.remove();
                 Context.getCommandContext().getHistoryManager().recordActivityEnd(executionEntity2);
                 System.err.println(findExecutionById + "----------------->>>>>>>>>>");


        }

        commandContext
                .getIdentityLinkEntityManager().deleteIdentityLinksByProcInstance(parentId);
        //要激活交路径
        executionEntity.setActive(true);
        //去掉无用的变量,不去掉,会导致很多莫名奇妙的问题
        executionEntity.removeVariable("loopCounter");
        //去掉多实例的变量,如果变量不知道是啥,自己从节点定义里查
        executionEntity.removeVariable("cdp_atuser");
        //触发事件监听器
        this.execute(executionEntity);
        InterpretableExecution propagatingExecution = null;
        if (this.desActivity.isScope()) {
            propagatingExecution = (InterpretableExecution) executionEntity.createExecution();
            executionEntity.setTransition(null);
            executionEntity.setActivity(null);
            executionEntity.setActive(false);
           // log.debug("create scope: parent {} continues as execution {}", execution, propagatingExecution);
            propagatingExecution.initialize();

        } else {
            propagatingExecution = executionEntity;
        }


        propagatingExecution.executeActivity(this.desActivity);

        return null;
    }


    protected ScopeImpl getScope(InterpretableExecution execution) {
        return (ScopeImpl) execution.getActivity();
    }

    /*
      触发事件监听器
     */
    public void execute(InterpretableExecution execution) {
        ScopeImpl scope = getScope(execution);
        List<ExecutionListener> exectionListeners = scope.getExecutionListeners(getEventName());
        for (ExecutionListener listener : exectionListeners) {
            execution.setEventName(getEventName());
            execution.setEventSource(scope);
            try {
                listener.notify(execution);
            } catch (RuntimeException e) {
                throw e;
            } catch (Exception e) {
                throw new PvmException("couldn't execute event listener : " + e.getMessage(), e);
            }

        }
    }

    protected String getEventName() {
        return org.activiti.engine.impl.pvm.PvmEvent.EVENTNAME_END;
    }

    /**
     * 构造参数 可以根据自己的业务需要添加更多的字段
     * @param taskId
     * @param executionId
     * @param desActivity
     * @param paramvar
     * @param currentActivity
     */
    public JDJumpTaskCmd(String taskId,String executionId, String parentId,
                         ActivityImpl desActivity, Map<String, Object> paramvar,
                         ActivityImpl currentActivity) {
        this.taskId=taskId;
        this.executionId = executionId;
        this.parentId = parentId;
        this.desActivity = desActivity;
        this.paramvar = paramvar;
        this.currentActivity = currentActivity;

    }
}

经测试,功能正常!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.08.22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档