ENGINE-02025 Variable ‘assigneeList‘ is not of the expected type ‘Collection‘

文章描述了在使用CamundaBPM框架处理动态审计流程时遇到的问题,由于assigneeList变量期望为Collection类型但实际传递的不是,导致监听器执行异常。作者分析了问题产生的原因和解决过程,最终通过在执行开始阶段设置assigneeList变量解决了问题。
摘要由CSDN通过智能技术生成

ENGINE-16004 Exception while closing command context: ENGINE-02025 Variable ‘assigneeList’ is not of the expected type ‘Collection’.

避雷!!!!

2023-10-23 16:33:04.560 ERROR 22116 — [nio-8080-exec-2] org.camunda.bpm.engine.context : ENGINE-16004 Exception while closing command context: ENGINE-02025 Variable ‘assigneeList’ is not of the expected type ‘Collection’.

org.camunda.bpm.engine.ProcessEngineException: ENGINE-02025 Variable ‘assigneeList’ is not of the expected type ‘Collection’.
at org.camunda.bpm.engine.impl.bpmn.behavior.BpmnBehaviorLogger.invalidVariableTypeException(BpmnBehaviorLogger.java:159) ~[camunda-engine-7.18.0.jar:7.18.0]

2023-10-23 16:33:04.566 ERROR 22116 — [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.camunda.bpm.engine.ProcessEngineException: ENGINE-02025 Variable ‘assigneeList’ is not of the expected type ‘Collection’.] with root cause

org.camunda.bpm.engine.ProcessEngineException: ENGINE-02025 Variable ‘assigneeList’ is not of the expected type ‘Collection’.
at org.camunda.bpm.engine.impl.bpmn.behavior.BpmnBehaviorLogger.invalidVariableTypeException(BpmnBehaviorLogger.java:159) ~[camunda-engine-7.18.0.jar:7.18.0]

1、问题产生原因:

​ 在使用Camunda Model 创建了一个动态设置审核人的流程:即在流程中不固定设置每个节点的审核人,然后流程审核进度,触发每个任务节点上的任务监听器creat 同时传入自定义节点类型的参数到后台,后台监听器实现类 通过该标识在去设置对应的受理人Assignee信息。 如下图

在这里插入图片描述

前面的几个普通类型的任务节点通过 TaskListeners(create) 任务监听器 都成功的完成了动态设置审核人的操作!

  • 后端Task Liteners 任务监听器的实现类代码
package cn.zhidasifang.camundaproject.camundaListeners.tasklisteners;

import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.delegate.DelegateTask;
import org.camunda.bpm.engine.delegate.Expression;
import org.camunda.bpm.engine.delegate.TaskListener;
import org.camunda.bpm.engine.history.HistoricTaskInstanceQuery;
import org.camunda.bpm.engine.runtime.ActivityInstance;
import org.camunda.bpm.engine.runtime.ProcessInstanceModificationInstantiationBuilder;
import org.camunda.bpm.engine.task.Task;
import org.springframework.stereotype.Component;

import java.beans.ExceptionListener;
import java.util.*;

/**
 * @Description:-任务监听器动态设置受理人Assignee流程的监听器实现类 【动态设置节点审核人】
 * --应用于Assignee受理人动态分配测试.bpmn 流程的TaskListener监听器
 * @ClassName: ListenersSetAssigneeProcess
 */

@Slf4j
@Component
@Data
@RequiredArgsConstructor
public class ListenersSetAssigneeProcess implements TaskListener {

    //任务监听器携带的参数值!!
    private Expression type;
    private Expression assignee;

    @Override
    public void notify(DelegateTask delegateTask) {
        //1.获取节点受理人AssigneeType类型
        //方式一:从TaskListeners-Field injection中获取传入的受理人类型参数
        String assigneeType = (String) type.getValue(delegateTask);
        //方式二:从task任务节点的Inputs中传入的参数获取类型
        String assigneeType2 = (String) delegateTask.getVariable("type");
        //todo-problem--该type参数是会迭代掉吗? 不同节点variable中存入的type参数是不同的!

        /*该任务还未创建 暂时为null
        TaskService taskService = delegateTask.getProcessEngine().getTaskService();
        Task task = taskService.createTaskQuery()
                .taskId(delegateTask.getId())
                .singleResult();*/
        //Task  = delegateTask.getProcessEngine().getTaskService().createTaskQuery().taskId(delegateTask.getId()).singleResult();
        RuntimeService runtimeService = delegateTask.getProcessEngine().getRuntimeService();
        ActivityInstance activityInstance = runtimeService.getActivityInstance(delegateTask.getProcessInstanceId());
        String activityName = activityInstance.getActivityName();
        log.info("当前节点名称" + activityName + "  审核类型 type=(TaskListeners中传入的type参数)" + assigneeType + " / (Inputs中设置的参数‘主要是否已经迭代,因为每个节点都会传入该参数来’)" + assigneeType2);

        //2.根据节点审核人类型assigneeType,动态设置节点审核人
        // TODO: 2023-10-20 拿到对应类型后需要通过指定类型人员,到对应的职员表中查询到对应的审核人,然后设置为该节点的审核人!!
        if (assigneeType.equalsIgnoreCase("BMJL")) { //部门经理
            String initiator = (String) delegateTask.getVariable("initiator"); //发起人
            delegateTask.setAssignee("bmjl");

        } else if (assigneeType.equalsIgnoreCase("BMZG")) { //部门主管
            String initiator = (String) delegateTask.getVariable("initiator");
            delegateTask.setAssignee("bmzg");
        } else if (assigneeType.equalsIgnoreCase("userId")) { //指定审核人员
            //指定人员的目前还只能通过监听器传入,应为全通过Inputs传入该参数会不会导致数据紊乱(Key 相同)!!
            String assigneeInputs = (String) delegateTask.getVariable("assignee");
            String assigneeTaskListeners = (String) assignee.getValue(delegateTask);
            delegateTask.setAssignee(assigneeTaskListeners);
        }
    }
}

上面几个节点都是能正常处理并动态设置审核人的。

2、解决过程:

任务执行调整到该流程设置的会签节点时,就出现了该错误!!!

  • 对会签节点的监听器做了很多的调整,通过很多方式来给会签节点的 受理人集合进行赋值,始终没能解决该问题。
 else if (assigneeType.equals("GSGC")) {
            //高层审核节点是会签节点
            System.out.println("assigneeType = " + assigneeType);
            //会签节点审核人设置
            /*
             11111通过集合(节点集合 variable参数的添加设置)的方式添加失败!!!!!!
            * */
            ArrayList<String> assigneeList = new ArrayList<>(3);
            assigneeList.add("gcUser1");
            assigneeList.add("gcUser2");
            assigneeList.add("gcUser3");
            //runtimeService.setVariable(delegateTask.getExecutionId(), "assigneeList", assigneeList);
            // 报错-- ENGINE-16004 Exception while closing command context: ENGINE-02025 Variable 'assigneeList' is not of the expected type 'Collection'.
//            delegateTask.setVariable("assigneeList",assigneeList);

            // 22222会签节点进行加签操作添加受理人Assignee--通过加签的方式失败!!---会签受理人集合会报错!!
            /*
            String taskDefinitionKey = delegateTask.getTaskDefinitionKey();
            String activityId1 = activityInstance.getActivityId();  //获取当前节点的activityId--后续加签需要使用到
            ProcessInstanceModificationInstantiationBuilder processInstanceModificationInstantiationBuilder = runtimeService.createProcessInstanceModification(delegateTask.getProcessInstanceId())
                    .startBeforeActivity(activityId1);
             */

            // TODO: 2023-10-20 会签模式下的审核人怎么添加,1.设置变量(创建时需要传入)  2.加签的方式时,也只能通过添加变量参数来实现   需要参考U8中的,后续改进,先忽略掉会签模式!!!
            // 33333尝试看该方法( 直接通过setAssignee(“xxx”)的方式添加审核人 )是否行得通!! 该方式排除掉[审核人集合依然会出现报错!!]
            // 44444--将会签集合去掉后 通过该方式 delegateTask.setAssignee() 设置审核人!! 失败,会签节点必须要设置审核代理人Assignee的备选List集合中!!
            /*delegateTask.setAssignee("gcUser1");
            delegateTask.setAssignee("gcUser2");
            delegateTask.setAssignee("gcUser3");*/
            /**
             * 问设置assigneeList变量必须提前设置吗,
             * 我实在第二个节点的时候配置start监听器去设置assigneeList的,
             * 但是在第一个节点complete就会报错,提示assigneeList变量不存在
             * [只能先暂时统一添加一个零时审核人 assignee,后续运行到该会签节点之后进行更改!!]
             * */
        }
  • 其实这里踩了一个坑,一直在调整监听器中的代码,尝试能找到某种可行的方式,将该会签任务的受理人集合进行赋值。但是忽略了一个点:报错是在任务流程转移到该会签节点的时候出现该错误。也就是没有检测到会签节点的受理人集合(未赋值variable中不存在),所有就根本不会进入Task Listeners(create) 监听器中,所有在怎么调整监听器代码都是无用功。
  • 然后就在该任务节点上设置了 Execution Liteners (start) 执行监听器 [ 因为节点上的 ExecutionListeners 执行监听器是快于 Task Listeners 任务监听器的 ]

在这里插入图片描述

​ 但是结果还是没能解决该问题,。。。。

  • 然后在继续提前 对 会签节点的 受理人集合进行赋值。 那就选择了连接线上设置一个 Execution Listeners(take),通过该连接线上的监听器完成对 会签节点的 受理人集合进行赋值。

在这里插入图片描述

这样就成功的解决了该问题。

导致该问题的原因,就是因为,当审核流程审核到会签节点时,检测到我们的会签节点 AssigneeList受理人集合是null 或者 variable中受理人集合还没赋值,就会导致该错误,同时就不能顺利的进入会签节点中即不会执行会签节点中相关的Listeners监听器了。

所有,我们需要在进入会签节点之前就将我们的会签节点受理人集合数据封装好!!!

  • 后端 Execution Listeners(连线上的take监听器) 监听器的实现类代码如下:
package cn.zhidasifang.camundaproject.camundaListeners.tasklisteners;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.engine.delegate.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.ArrayList;

/**
 * @Description:节点开始前的监听器,通过input中的参数设置对应的审核人信息!---动态地为任务分配办理人,而不是在流程定义中静态地指定。
 * @ClassName: StartListennersSetAssignee
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class TestTempListeners implements ExecutionListener {
//这里定义的Expression  字段名称必须要和流程中 Field Injection 名称一致
    private Expression type;
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
    *@Description---Exception执行监听器实现类
    *@Param [execution]
    *@return void
    */
    @Override
    public void notify(DelegateExecution execution) throws Exception {
        String value =(String) type.getValue(execution);
        System.out.println("Exception Listeners 执行监听器获取数据:value = " + value);
        ArrayList<String> assigneeList = new ArrayList<>(3);
        assigneeList.add("gcUser1");
        assigneeList.add("gcUser2");
        assigneeList.add("gcUser3");
        execution.setVariable("assigneeList",assigneeList);
        System.out.println("节点添加受理人 assignee 成功!!");
    }
}

备注:会签节点中,包含多个Task任务节点!!,每一个受理人Assignee都是单独的一个任务,都会单独的调用一次会签节点中的 Task Listeners 任务监听器!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值