flowable/activiti 如何退回上一个节点?

2021-03-30 19:59发布

3条回答
studentaaa
2楼 · 2021-04-04 09:19

//flowable/activiti 如何退回上一个节点?下面使用代码演示:


//退回上一个节点: public String rollBackWorkFlow(String taskId) {   this.taskService=processEngine.getTaskService();   this.historyService = processEngine.getHistoryService();   this.repositoryService = processEngine.getRepositoryService();   this.runtimeService = processEngine.getRuntimeService();     try {         Map variables;         // 取得当前任务.当前任务节点         HistoricTaskInstance currTask = historyService                 .createHistoricTaskInstanceQuery().taskId(taskId)                 .singleResult();         // 取得流程实例,流程实例         ProcessInstance instance = runtimeService                 .createProcessInstanceQuery()                 .processInstanceId(currTask.getProcessInstanceId())                 .singleResult();         if (instance == null) {          log.info("流程结束");             log.error("出错啦!流程已经结束");             return "ERROR";         }         variables = instance.getProcessVariables();         // 取得流程定义         ProcessDefinitionEntity definition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)                 .getDeployedProcessDefinition(currTask                         .getProcessDefinitionId());         if (definition == null) {          log.info("流程定义未找到");             log.error("出错啦!流程定义未找到");             return "ERROR";         }         // 取得上一步活动         ActivityImpl currActivity = ((ProcessDefinitionImpl) definition)                 .findActivity(currTask.getTaskDefinitionKey());         //也就是节点间的连线         List nextTransitionList = currActivity                 .getIncomingTransitions();         // 清除当前活动的出口         List oriPvmTransitionList = new ArrayList();         //新建一个节点连线关系集合         List pvmTransitionList = currActivity                 .getOutgoingTransitions();         //         for (PvmTransition pvmTransition : pvmTransitionList) {             oriPvmTransitionList.add(pvmTransition);         }         pvmTransitionList.clear();         // 建立新出口         List newTransitions = new ArrayList();         for (PvmTransition nextTransition : nextTransitionList) {             PvmActivity nextActivity = nextTransition.getSource();             ActivityImpl nextActivityImpl = ((ProcessDefinitionImpl) definition)                     .findActivity(nextActivity.getId());             TransitionImpl newTransition = currActivity                     .createOutgoingTransition();             newTransition.setDestination(nextActivityImpl);             newTransitions.add(newTransition);         }         // 完成任务         List tasks = taskService.createTaskQuery()                 .processInstanceId(instance.getId())                 .taskDefinitionKey(currTask.getTaskDefinitionKey()).list();         for (Task task : tasks) {             taskService.complete(task.getId(), variables);             historyService.deleteHistoricTaskInstance(task.getId());         }         // 恢复方向         for (TransitionImpl transitionImpl : newTransitions) {             currActivity.getOutgoingTransitions().remove(transitionImpl);         }         for (PvmTransition pvmTransition : oriPvmTransitionList) {             pvmTransitionList.add(pvmTransition);         }         log.info("OK");         log.info("流程结束");         return "SUCCESS";     } catch (Exception e) {      log.error("失败");         log.error(e.getMessage());         return "ERROR";     } } //回退到指定节点: public String rollBackToAssignWorkFlow(String taskId,String destTaskkey) {   this.taskService=processEngine.getTaskService();   this.historyService = processEngine.getHistoryService();   this.repositoryService = processEngine.getRepositoryService();   this.runtimeService = processEngine.getRuntimeService();     try {         Map variables;         // 取得当前任务.当前任务节点         HistoricTaskInstance currTask = historyService                 .createHistoricTaskInstanceQuery().taskId(taskId)                 .singleResult();         // 取得流程实例,流程实例         ProcessInstance instance = runtimeService                 .createProcessInstanceQuery()                 .processInstanceId(currTask.getProcessInstanceId())                 .singleResult();         if (instance == null) {          log.info("流程结束");             log.error("出错啦!流程已经结束");             return "ERROR";         }         variables = instance.getProcessVariables();         // 取得流程定义         ProcessDefinitionEntity definition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)                 .getDeployedProcessDefinition(currTask                         .getProcessDefinitionId());         if (definition == null) {          log.info("流程定义未找到");             log.error("出错啦!流程定义未找到");             return "ERROR";         }        //取得当前活动节点         ActivityImpl currActivity = ((ProcessDefinitionImpl) definition)                 .findActivity(currTask.getTaskDefinitionKey());          log.info("currActivity"+currActivity);          // 取得上一步活动         //也就是节点间的连线         //获取来源节点的关系         List nextTransitionList = currActivity.getIncomingTransitions();         // 清除当前活动的出口         List oriPvmTransitionList = new ArrayList();         //新建一个节点连线关系集合         //获取出口节点的关系         List pvmTransitionList = currActivity                 .getOutgoingTransitions();         //         for (PvmTransition pvmTransition : pvmTransitionList) {             oriPvmTransitionList.add(pvmTransition);         }         pvmTransitionList.clear();         // 建立新出口         List newTransitions = new ArrayList();         for (PvmTransition nextTransition : nextTransitionList) {             PvmActivity nextActivity = nextTransition.getSource();                         log.info("nextActivity"+nextActivity);                         log.info("nextActivity.getId()"+nextActivity.getId());                         //destTaskkey             ActivityImpl nextActivityImpl = ((ProcessDefinitionImpl) definition)                    // .findActivity(nextActivity.getId());               .findActivity(destTaskkey);             TransitionImpl newTransition = currActivity                     .createOutgoingTransition();             newTransition.setDestination(nextActivityImpl);             newTransitions.add(newTransition);         }         // 完成任务         List tasks = taskService.createTaskQuery()                 .processInstanceId(instance.getId())                 .taskDefinitionKey(currTask.getTaskDefinitionKey()).list();         for (Task task : tasks) {             taskService.complete(task.getId(), variables);             historyService.deleteHistoricTaskInstance(task.getId());         }         // 恢复方向         for (TransitionImpl transitionImpl : newTransitions) {             currActivity.getOutgoingTransitions().remove(transitionImpl);         }         for (PvmTransition pvmTransition : oriPvmTransitionList) {          pvmTransitionList.add(pvmTransition);         }         log.info("OK");         log.info("流程结束");         return "SUCCESS";     } catch (Exception e) {      log.error("失败");         log.error(e.getMessage());         return "ERROR";     } }  

靓猴一枚
3楼 · 2021-08-29 09:53

一、驳回/退回上一步/退回到(历史某一个节点)


        我们经常需要工作流中退回上一步,或者退回历史某一个节点。但由于流程的场景是很复杂的,回退有以下一些场景:


1.串行路线上的退回:流程中没有任何网关(排他网关/并行网关)和会签多实例。


2.退回到并行网关分支中的某一个节点上:


3.并行网关中的某一个分支节点上发起退回,退回到并行网关前面的某一个节点上


4.子流程中退回到主干流程中某一个节点/主干流程退回到子流程中某一个节点。


如下图:


 




 


二、flowable实现:


1.普通串行路线上的退回(此流程中没有并行网关的退回时),此方法支持普通串行节点/会签多实例节点/排他网关节点:


runtimeService.createChangeActivityStateBuilder()

        .processInstanceId(proInstanceId)

        .moveActivityIdsToSingleActivityId(curTaskKeys, targetTaskKey)

        .changeState();

或者


moveActivityIdTo(String currentActivityId,String newActivityId);

2.并行网关中发起退回(即撤销当前的网关),这个地方不能用moveActivityIdTo(String currentActivityId,String newActivityId);是因为当某一个分支完成,它的is_active为0,另一条分支没有完成时。这时候这个方法是取不到所的分支的key的,它只有is_active为1的key能取到,不然就会造成多一条垃圾数据,同时再走并行时,任何一个分支不会等另一个分支就完走到分支的合并节点上,这就是bug,所以要改为以下方法:


// 并行网关的退回

List currentExecutionIds = new ArrayList<>();

List executions = runtimeService.createExecutionQuery().parentId(proInstanceId).list();

for (Execution execution : executions) {

    System.out.println("并行网关节点数:"+execution.getActivityId());

    currentExecutionIds.add(execution.getId());

}

runtimeService.createChangeActivityStateBuilder()

        .moveExecutionsToSingleActivityId(currentExecutionIds, targetTaskKey)

        .changeState();

3.退回到并行网关中的某一个节点:经试验退回时必须同时退回并行网关中的所有分支。


List targetTaskKeys = new ArrayList<>();

targetTaskKeys.add("sid-CA74ADED-7E70-451D-951C-95988BFC3F07");

targetTaskKeys.add("sid-7922C598-74FD-4848-95AC-D9790AF68432");

 

runtimeService.createChangeActivityStateBuilder()

        .processInstanceId(proInstanceId)

        .moveSingleActivityIdToActivityIds("sid-CAD50E6F-7E0C-437D-816B-DDBA1A976A79", targetTaskKeys)

        .changeState();

4.主干流程和子流程的退回(没有试验过),官方提供了以下方法:



moveActivityIdToParentActivityId(String currentActivityId, String newActivityId)


moveActivityIdToSubProcessInstanceActivityId(String currentActivityId, String newActivityId, String callActivityId)

moveActivityIdToSubProcessInstanceActivityId(String currentActivityId,  String newActivityId, String callActivityId,Integer subProcessDefinitionVersion)

zgtl_20
4楼 · 2021-12-10 08:55

1、自己新写了一个Command,需要实现org.flowable.engine.common.impl.interceptor.Command

 接口,覆盖其execute

 方法,并增加一个有参构造方法

20170830170318175.png

20170830170337075.png





 2、通过flowable的org.flowable.engine.ManagementService,调用自己写的Command,实现回退。


  manageMentService.executeCommand(new JumpCmd(flowElement,currentTask,hisTaskEntity)); 


  //第一个参数flowElement是需要跳转到的节点信息,这里因为要求的是回退到上一节点,所以这里只上一节点信息


  //第二个参数是值当前任务实体


  //第三个参数指需要跳转到的节点的任务实体,这里指上一节点的任务实体

 

 

 


 说明:对于无分支的流程,需要回退到上一节点,可以直接利用flowable现有的API,调用方法如下:


 runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).cancelActivityId(currentNode).startActivityId(beforeNode).changeState();


相关问题推荐

  • 回答 2

    Statement的execute(String query)方法用来执行任意的SQL查询,如果查询的结果是一个ResultSet,这个方法就返回true。如果结果不是ResultSet,比如insert或者update查询,它就会返回false。我们可以通过它的getResultSet方法来获取ResultSet,或者通过getUpda...

  • 回答 22

    忙的时候项目期肯定要加班 但是每天加班应该还不至于

  • 回答 108
    已采纳

    虽然Java人才越来越多,但是人才缺口也是很大的,我国对JAVA工程师的需求是所有软件工程师当中需求大的,达到全部需求量的60%-70%,所以Java市场在短时间内不可能饱和。其次,Java市场不断变化,人才需求也会不断增加。马云说过,未来的制造业要的不是石油,...

  • 回答 5
    已采纳

    工信部证书含金量较高。工信部是国务院的下属结构,具有发放资质、证书的资格。其所发放的证书具有较强的权威性,在全国范围内收到认可,含金量通常都比较高。 工信部证书,其含义也就是工信部颁发并承认的某项技能证书,是具有法律效力的,并且是国家认可的...

  • 回答 70
    已采纳

    学Java好不好找工作?看学完Java后能做些什么吧。一、大数据技术Hadoop以及其他大数据处理技术都是用Java或者其他,例如Apache的基于Java 的 HBase和Accumulo以及ElasticSearchas。但是Java在此领域并未占太大空间,但只要Hadoop和ElasticSearchas能够成长壮...

  • 回答 16
    已采纳

    就是java的基础知识啊,比如Java 集合框架;Java 多线程;线程的五种状态;Java 虚拟机;MySQL (InnoDB);Spring 相关;计算机网络;MQ 消息队列诸如此类

  • 回答 12

    #{}和${}这两个语法是为了动态传递参数而存在的,是Mybatis实现动态SQL的基础,总体上他们的作用是一致的(为了动态传参),但是在编译过程、是否自动加单引号、安全性、使用场景等方面有很多不同,下面详细比较两者间的区别:1.#{} 是 占位符 :动态解析 ...

  • 回答 62

    没问题的,专科学历也能学习Java开发的,主要看自己感不感兴趣,只要认真学,市面上的培训机构不少都是零基础课程,能跟得上,或是自己先找些资料学习一下。

  • 回答 4

    1、反射对单例模式的破坏采用反射的方式另辟蹊径实例了该类,导致程序中会存在不止一个实例。解决方案其思想就是采用一个全局变量,来标记是否已经实例化过了,如果已经实例化过了,第 二次实例化的时候,抛出异常2、clone()对单例模式的破坏当需要实现单例的...

  • 回答 5

     优点: 一、实例控制  单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。 二、灵活性  因为类控制了实例化过程,所以类可以灵活更改实例化过程。 缺点: 一、开销  虽然数量很少,但如果每次对象请求引用时都要...

  • 回答 4

    这个主要是看你数组的长度是多少, 比如之前写过的一个程序有个数组存的是各个客户端的ip地址:string clientIp[4]={XXX, xxx, xxx, xxx};这个时候如果想把hash值对应到上面四个地址的话,就应该对4取余,这个时候p就应该为4...

  • 回答 6

     哈希表的大小 · 关键字的分布情况 · 记录的查找频率 1.直接寻址法:取关键字或关键字的某个线性函数值为散列地址。即H(key)=key或H(key) = a·key + b,其中a和b为常数(这种散列函数叫做自身函数)。...

  • 回答 6

    哈希表的大小取决于一组质数,原因是在hash函数中,你要用这些质数来做模运算(%)。而分析发现,如果不是用质数来做模运算的话,很多生活中的数据分布,会集中在某些点上。所以这里最后采用了质数做模的除数。 因为用质数做了模的除数,自然存储空间的大小也用质数了...

  • 回答 2

    是啊,哈希函数的设计至关重要,好的哈希函数会尽可能地保证计算简单和散列地址分布均匀,但是,我们需要清楚的是,数组是一块连续的固定长度的内存空间

  • 回答 3

     解码查表优化算法,seo优化

  • 回答 5

    1.对对象元素中的关键字(对象中的特有数据),进行哈希算法的运算,并得出一个具体的算法值,这个值 称为哈希值。2.哈希值就是这个元素的位置。3.如果哈希值出现冲突,再次判断这个关键字对应的对象是否相同。如果对象相同,就不存储,因为元素重复。如果对象不同,就...

没有解决我的问题,去提问