zoukankan      html  css  js  c++  java
  • Activiti7 结束/终止流程

    1.  结束/终止 正在运行的流程实例

    思路:跟回退一样的思路一样,直接从当前节点跳到结束节点(EndEvent) 

    /**
     * 结束任务
     * @param taskId    当前任务ID
     */
    public void endTask(String taskId) {
        //  当前任务
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
    
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        List endEventList = bpmnModel.getMainProcess().findFlowElementsOfType(EndEvent.class);
        FlowNode endFlowNode = endEventList.get(0);
        FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());
    
        //  临时保存当前活动的原始方向
        List originalSequenceFlowList = new ArrayList<>();
        originalSequenceFlowList.addAll(currentFlowNode.getOutgoingFlows());
        //  清理活动方向
        currentFlowNode.getOutgoingFlows().clear();
    
        //  建立新方向
        SequenceFlow newSequenceFlow = new SequenceFlow();
        newSequenceFlow.setId("newSequenceFlowId");
        newSequenceFlow.setSourceFlowElement(currentFlowNode);
        newSequenceFlow.setTargetFlowElement(endFlowNode);
        List newSequenceFlowList = new ArrayList<>();
        newSequenceFlowList.add(newSequenceFlow);
        //  当前节点指向新的方向
        currentFlowNode.setOutgoingFlows(newSequenceFlowList);
    
        //  完成当前任务
        taskService.complete(task.getId());
    
        //  可以不用恢复原始方向,不影响其它的流程
    //        currentFlowNode.setOutgoingFlows(originalSequenceFlowList);
    }
    

    补充1:关于BUSINESS_KEY_

    BUSINESS_KEY_ 字段是用于将业务系统与Actititi工作流关联的关键字段,通常我们用它来存放业务表的ID,比如:请假ID、报销ID等等。

    但是,通常咱们系统不可能只有一个流程,假设我们做的是一个OA系统,那么公司的流程有请假、采购、报销等等流程,那这一个字段如何区分到底是哪个业务流程的ID呢,换言之,假设BUSINESS_KEY_这个字段现在是2,那么我怎么知道这个2是请假表的ID,还是采购表的ID呢?因此,要想通过这个一个字段区分不同的类型就要求这个字段是唯一的,比如我们可以加上业务标识,比如:holiday:2,purchase:3等等。还有一种方式,利用另外一个空闲字段TENANT_ID_,我们可以把业务类型存到TENANT_ID_字段中,这样TENANT_ID_和BUSINESS_KEY_两个字段就能唯一确定是哪个业务的那个ID。

    /**
     * 7.1.0.M6的act_ru_task表中有BUSINESS_KEY_字段,因此可以直接task.getBusinessKey()
     * 而7.1.0.M5中没有这个字段,因此要想获取BUSINESS_KEY_必须从act_ru_execution表中取
     */
    @Test
    public void testBusinessKey() {
        List<Task> taskList = taskService.createTaskQuery().taskCandidateOrAssigned("lisi").taskTenantId("11").list();
        Set<String> processInstanceIds = taskList.stream().map(Task::getProcessInstanceId).collect(Collectors.toSet());
        List<ProcessInstance> processInstances = runtimeService.createProcessInstanceQuery().processInstanceIds(processInstanceIds).list();
        
        List<String> businessKeyList = processInstances.stream().map(ProcessInstance::getBusinessKey).collect(Collectors.toList());
        System.out.println(businessKeyList);
    
        Pattern pattern = Pattern.compile("^(\w+):(\d+)$");
        
        List<Integer> businessIds = new ArrayList<>();
        businessKeyList.forEach(businessKey->{
            Matcher matcher = pattern.matcher(businessKey);
            if (matcher.find()) {
                String id = matcher.group(2);
                businessIds.add(Integer.valueOf(id));
            }
        });
    }
    

    补充2:Activiti不同版本的Bug

    首先,我发现不同版本的表结构不一样,当用 7.1.0.M5 版本时,启动就报错,缺少字段

    org.apache.ibatis.exceptions.PersistenceException: 
    ### Error updating database.  Cause: java.sql.SQLSyntaxErrorException: Unknown column 'VERSION_' in 'field list'
    ### The error may exist in org/activiti/db/mapping/entity/Deployment.xml
    ### The error may involve org.activiti.engine.impl.persistence.entity.DeploymentEntityImpl.insertDeployment-Inline
    ### The error occurred while setting parameters
    ### SQL: insert into ACT_RE_DEPLOYMENT(ID_, NAME_, CATEGORY_, KEY_, TENANT_ID_, DEPLOY_TIME_, ENGINE_VERSION_, VERSION_, PROJECT_RELEASE_VERSION_)     values(?, ?, ?, ?, ?, ?, ?, ?, ?)
    ### Cause: java.sql.SQLSyntaxErrorException: Unknown column 'VERSION_' in 'field list'
        at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30) ~[mybatis-3.5.0.jar:3.5.0]
        at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:200) ~[mybatis-3.5.0.jar:3.5.0]
        at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185) ~[mybatis-3.5.0.jar:3.5.0]
        at org.activiti.engine.impl.db.DbSqlSession.flushRegularInsert(DbSqlSession.java:787) ~[activiti-engine-7.1.0.M5.jar:na]
        at org.activiti.engine.impl.db.DbSqlSession.flushInsertEntities(DbSqlSession.java:662) ~[activiti-engine-7.1.0.M5.jar:na]
        at org.activiti.engine.impl.db.DbSqlSession.flushInserts(DbSqlSession.java:642) ~[activiti-engine-7.1.0.M5.jar:na]
        at org.activiti.engine.impl.db.DbSqlSession.flush(DbSqlSession.java:525) ~[activiti-engine-7.1.0.M5.jar:na]

    解决办法也很简单,将缺失的字段加上即可:

    ALTER TABLE `act_re_deployment` 
    ADD COLUMN `VERSION_` int(11) NULL DEFAULT NULL,
    ADD COLUMN `PROJECT_RELEASE_VERSION_` varchar(255) NULL DEFAULT NULL;

    其次,我发现在启动流程实例查询流程定义时,7.1.0.M5是按版本升序取第一个,而7.1.0.M6是降序

    同时,还发现7.1.0.M6有一个明显的Bug,这个Bug会导致当有多个部署的时候,即当act_re_deployment表中的记录多于1条时,就无法使用processRuntime.start()启动流程实例

     

    本着用新不用旧的原则,还是建议用7.1.0.M6

    还有一个bug,这个bug发生在当使用原生的taskService完成任务时,多次设置同一个流程变量的值后者不会覆盖前者。即,ACT_RU_VARIABLE表中变量的值没有更新。

    为了说明这个问题,看下面这个图:

    节点“1”完成任务时设置result==3,于是后面的流程永远是1->3->1->3->...  ,即使下一次执行时result==1,流程也不会走到2。经过分析,我猜测对同一个变量多次赋值,后者没有覆盖前者,也就是说第2次赋值没有生效,查看ACT_RU_VARIABLE表果然是这样,变量的值没有更新。经过反复试验,我发现用taskRuntime.complete()完成任务时就不会出现这个问题,流程变量的值会正常更新。

    
    Map<String, Object> variables = new HashMap<>();
    variables.put("result", 3);
    
    //	这样写的话,多次对同一个流程变量赋值时,流程变量的值不会更新,即后面的赋值永远是不生效的
    Task task = taskService.createTaskQuery().taskId("1234").singleResult();
    taskService.complete(task.getId(), variables);
    
    //	这样写的话,就很完美,ACT_RU_VARIABLE表的流程变量的值正常更新
    taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId("1234").withVariables(variables).build());
    

    补充3:任务监听器

    @Slf4j
    @Component
    public class TaskCreateListener implements TaskRuntimeEventListener<TaskCreatedEvent> {
        @Override
        public void onEvent(TaskCreatedEvent event) {
        	System.out.println("任务被创建");
        }
    }
    
    @Slf4j
    @Component
    public class TaskAssignedListener implements TaskRuntimeEventListener<TaskAssignedEvent> {
        @Override
        public void onEvent(TaskAssignedEvent event) {
    	System.out.println("任务被指派");
        }
    }
    
    @Slf4j
    @Component
    public class TaskCompletedListener implements TaskRuntimeEventListener<TaskCompletedEvent> {
        @Override
        public void onEvent(TaskCompletedEvent event) {
    	System.out.println("任务被完成");
        }
    }
    

    关于Activiti就到此为止了,以后也不想再碰这玩意儿了,太难用了

  • 相关阅读:
    Java SSL证书的安装
    zookeeper集群配置
    ERROR org.apache.zookeeper.ClientCnxn:532
    线程池c3p0和dbcp2的配置初始化实例
    SIP/2.0 403 Forbidden(Invalid domain in From: header)
    OkHttp实现文件上传进度
    Http 缓存机制
    Cookie、Session 和 Token区别
    RecyclerView-- 侧滑删除和拖动排序
    RecyclerView--添加头部和底部
  • 原文地址:https://www.cnblogs.com/cjsblog/p/15104772.html
Copyright © 2011-2022 走看看