Camunda 工作流节点跳转 - 多实例节点判断和跳转

在多种工作流引擎中,Camunda框架对流程的处理控制更为强大、灵活。

在应对流程节点按业务需要进行自由跨节点跳转的需求时,通过代码自由控制节点的跳转在Camunda中是支持的,并且提供了编码方法,其中多实例的处理上有一些区别要特别注意:

1、单实例节点,或者不是基于集合配置的多实例节点。

2、多实例 userTask 节点,在 <multiInstanceLoopCharacteristics ...> 中通过配置 collectionelementVariableuserTask 提供 assignee 变量引用的。

其中第1点,跳转节点的主要代码片段如下:

ProcessInstance processInstance = ...;
runtimeService.createProcessInstanceModification(processInstance.getId())
  .cancelAllForActivity("Activity_8dsxc8ds") // 取消当前节点所有活动中的Task任务
  .startBeforeActivity("Activity_0qsw8c1") // 目标节点Id,在流程图中看,固定值(一般起一个正规的名字)
  .setVariable("带入所需变量key", "变量值Object类型")
  .setAnnotation("跳转到目标节点") // 为当前实例的修改添加注释,虽然没有实际业务作用,但是推荐使用
  .execute();

如果多实例活动是基于集合配置的,则执行 startBeforeActivity 指令时不会考虑集合,并且不会为附加实例填充集合元素变量,针对这种情况,需要使用下面的处理方法。

第2点,基于集合的多实例跳转节点的跳转时,需要在节点Id后追加特定字符串 #multiInstanceBody,示例如下:

ProcessInstance processInstance = ...;
runtimeService.createProcessInstanceModification(processInstance.getId())
  .cancelAllForActivity("Activity_8dsxc8ds")
  .startBeforeActivity("Activity_0qsw8c1#multiInstanceBody") // 目标节点是多实例节点,节点Id后面必须增加后缀 #multiInstanceBody
  .setVariable("带入所需变量key", "变量值Object类型")
  .setAnnotation("跳转到目标节点") // 为当前实例的修改添加注释,虽然没有实际业务作用,但是推荐使用
  .execute();

注:对于目标节点是多实例的节点,如果不在节点Id后面追加框架约定的字符串 #multiInstanceBody,则不能自动执行触发多实例节点配置的 <multiInstanceLoopCharacteristics .... > 中的集合变量处理。

对于如何判断一个节点是多实例节点,可以参考使用下面我写好的一个判断方法:


    /**
     * 判断一个节点是否为多实例节点
     *
     * @param execution 监听器 DelegateExecution 对象
     * @param activityId 节点Id
     * @return 是否多实例节点
     */
    public boolean isMultiInstanceActivity(DelegateExecution execution, String activityId){
    
    
        Activity activity = execution.getBpmnModelInstance().getModelElementById(activityId);
        return activity.getLoopCharacteristics() != null;
    }
    
    /**
     * 判断一个节点是否为多实例节点(不推荐的方法,保留代码仅为参考)
     * 
     * @param repositoryService 可以注入Camunda对象直接使用
     * @param processDefinitionId 流程定义Id
     * @param activityId 节点Id
     * @return 是否多实例节点
     */
    @Deprecated
    public boolean isMultiInstanceActivity(RepositoryService repositoryService, String processDefinitionId, String activityId){
    
    
        boolean isMultiInstanceActivity = false;
        BpmnModelInstance bpmnModelInstance = repositoryService.getBpmnModelInstance(processDefinitionId);
        Optional<Process> processOptional =
                bpmnModelInstance.getModelElementsByType(Process.class)
                        .stream().filter(p -> p.getId().equals(processDefinitionId) || processDefinitionId.startsWith(p.getId().concat(":")))
                        .findFirst();
        if(processOptional.isPresent()){
    
    
            Process process = processOptional.get();
            Optional<FlowElement> activityOptional = process.getFlowElements()
                    .stream().filter(flowElement -> flowElement.getId().equals(activityId)).findFirst();
            if(activityOptional.isPresent()){
    
    
                isMultiInstanceActivity =
                        CollectionUtils.isNotEmpty(activityOptional.get().getChildElementsByType(MultiInstanceLoopCharacteristics.class));
            }
        }
        return isMultiInstanceActivity;
    }

官方参考文档:https://docs.camunda.org/manual/7.19/user-guide/process-engine/process-instance-modification/#modify-multi-instance-activity-instances


(END)

扫描二维码关注公众号,回复: 16694252 查看本文章

猜你喜欢

转载自blog.csdn.net/catoop/article/details/132450345
今日推荐