美文网首页
activiti多实例节点的任意跳转

activiti多实例节点的任意跳转

作者: 爱余星痕 | 来源:发表于2018-08-22 09:20 被阅读0次

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

    /**
         * 流程转向操作
         * 
         * @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也走向了驳回。
    那怎么整,上网查了一下,发现了分享牛的代码,但他的代码存在问题,不支持多实例跳转多实例。
    后续将代码修改如下:

    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: 自由跳转流程
     * @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;
    
        }
    }
    
    

    经测试,功能正常!

    相关文章

      网友评论

          本文标题:activiti多实例节点的任意跳转

          本文链接:https://www.haomeiwen.com/subject/vmleiftx.html