ActivitiIllegalArgumentException: Variable assigneeList‘ is not a Collection

Activiti 7.1.0.M5多实例任务转换错误:assigneeList类型问题

记录activiti7.1.0.M5版本在多实例任务通过时会发现报错, 即使设置了assigneeList的list数据但是提示的是转换有问题

 ActivitiIllegalArgumentException: Variable assigneeList' is not a Collection(String), ActivitiIllegalArgumentException: Variable assigneeList' is not a Collection(String), org.activiti.engine.ActivitiIllegalArgumentException: Variable assigneeList' is not a Collection
    at org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior.resolveAndValidateCollection(MultiInstanceActivityBehavior.java:225)
    at org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior.resolveNrOfInstances(MultiInstanceActivityBehavior.java:184)
    at org.activiti.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior.leave(ParallelMultiInstanceBehavior.java:108)
    at org.activiti.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior.leave(AbstractBpmnActivityBehavior.java:55)
    at org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior.trigger(UserTaskActivityBehavior.java:270)
    at org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior.trigger(MultiInstanceActivityBehavior.java:157)
    at org.activiti.engine.impl.agenda.TriggerExecutionOperation.run(TriggerExecutionOperation.java:38)
    at org.activiti.engine.impl.interceptor.CommandInvoker.executeOperation(CommandInvoker.java:73)
    at org.activiti.engine.impl.interceptor.CommandInvoker.executeOperations(CommandInvoker.java:57)
    at org.activiti.engine.impl.interceptor.CommandInvoker.execute(CommandInvoker.java:42)
    at org.activiti.engine.impl.interceptor.TransactionContextInterceptor.execute(TransactionContextInterceptor.java:48)
    at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:59)
    at org.activiti.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:47)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
    at org.activiti.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:45)
    at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:29)
    at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:44)
    at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:39)
    at org.activiti.engine.impl.TaskServiceImpl.complete(TaskServiceImpl.java:202)
    at cn.iocoder.yudao.module.bpm.service.task.BpmTaskServiceImpl.approveTask(BpmTaskServiceImpl.java:259)
    at cn.iocoder.yudao.module.bpm.service.task.BpmTaskServiceImpl$$FastClassBySpringCGLIB$$5c73399a.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)
    at cn.iocoder.yudao.module.bpm.service.task.BpmTaskServiceImpl$$EnhancerBySpringCGLIB$$5ddc427b.approveTask(<generated>)
    at cn.iocoder.yudao.module.bpm.controller.admin.task.BpmTaskController.approveTask(BpmTaskController.java:48)
    at cn.iocoder.yudao.module.bpm.controller.admin.task.BpmTaskController$$FastClassBySpringCGLIB$$5246e6e1.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:123)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
    at cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect.around0(OperateLogAspect.java:96)
    at cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect.around(OperateLogAspect.java:77)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:61)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)
    at cn.iocoder.yudao.module.bpm.controller.admin.task.BpmTaskController$$EnhancerBySpringCGLIB$$199a431.approveTask(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:920)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:684)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at de.codecentric.boot.admin.server.ui.web.servlet.HomepageForwardingFilter.doFilter(HomepageForwardingFilter.java:78)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:111)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at cn.iocoder.yudao.framework.activiti.core.web.ActivitiWebFilter.doFilterInternal(ActivitiWebFilter.java:30)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter.doFilterInternal(TenantSecurityWebFilter.java:98)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:121)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
    at cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter.doFilterInternal(JWTAuthenticationTokenFilter.java:60)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
    at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at cn.iocoder.yudao.framework.tenant.core.web.TenantContextWebFilter.doFilterInternal(TenantContextWebFilter.java:32)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter.doFilterInternal(CacheRequestBodyFilter.java:22)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter.doFilterInternal(TraceFilter.java:30)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:359)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:889)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1735)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

 搜了下对应的issue, 需要修改application.properties, 添加: spring.activiti.serializePOJOsInVariablesToJson=false

或者application.yml添加: 

spring:
  activiti:
    serialize-p-o-j-os-in-variables-to-json: false

​​​​​https://github.com/Activiti/Activiti/issues/2364​​​​​​​s​​​​​​​d

 

 

<think>我们正在处理Activiti流程引擎中的变量类型不匹配问题。具体错误是:`IllegalArgumentException: Variable handleDepts is not a Collection`。这意味着在某个操作中,Activiti期望变量`handleDepts`是一个集合(Collection)类型,但实际上它并不是。 ### 问题分析 1. **错误场景**:在Activiti流程中,当我们尝试使用`handleDepts`变量时,引擎要求该变量必须是一个集合(如List、Set等),但实际传入的可能是字符串、数字或其他非集合类型。 2. **常见原因**: - **任务分配**:在任务分配中,我们可能将`handleDepts`变量用于多用户任务分配(如会签、多候选人任务),这时Activiti要求该变量必须是一个集合。 - **网关条件**:在排他网关(Exclusive Gateway)的条件表达式中,如果使用了`handleDepts`变量进行集合操作(如判断是否包含某个元素),但该变量不是集合类型。 - **服务调用**:在调用`taskService.complete(taskId, variables)`时,传入的`handleDepts`变量不是集合类型,而流程定义中要求它是集合。 ### 解决方案 #### 1. 确保变量类型正确 在设置流程变量时,确保`handleDepts`是`java.util.Collection`的实现类(如ArrayList、HashSet): ```java // 错误示例:设置字符串 execution.setVariable("handleDepts", "dept1,dept2"); // 字符串,不是集合 // 正确示例:设置为集合 List<String> depts = Arrays.asList("dept1", "dept2"); execution.setVariable("handleDepts", depts); ``` #### 2. 检查流程定义 在流程定义文件(BPMN)中,检查使用`handleDepts`变量的地方: - **用户任务分配**:如果用于多候选人,必须使用集合。 ```xml <userTask id="task1" name="审批"> <potentialOwner> <resourceAssignmentExpression> <formalExpression>${handleDepts}</formalExpression> </resourceAssignmentExpression> </potentialOwner> </userTask> ``` 这里`${handleDepts}`必须返回字符串集合(如`["group1","group2"]`)或用户ID集合。 - **网关条件**:在排他网关的条件表达式中,如果使用类似`${handleDepts.contains('dept1')}`的表达式,则`handleDepts`必须是集合。 #### 3. 修改变量获取方式 如果变量已经存储为字符串,可以将其转换为集合: ```java Object variable = runtimeService.getVariable(executionId, "handleDepts"); if (variable instanceof String) { String deptString = (String) variable; List<String> deptList = Arrays.asList(deptString.split(",")); runtimeService.setVariable(executionId, "handleDepts", deptList); } ``` #### 4. 使用变量序列化 Activiti支持自定义变量序列化。如果必须存储复杂对象,可以实现`VariableType`接口并注册: ```java public class CollectionVariableType implements VariableType { // 实现序列化和反序列化方法 // ... } // 注册到ProcessEngineConfiguration processEngineConfiguration.getVariableTypes().addType(new CollectionVariableType()); ``` #### 5. 异常处理 在任务完成或流程操作时捕获异常并转换变量类型: ```java try { taskService.complete(taskId, variables); } catch (ActivitiIllegalArgumentException e) { if (e.getMessage().contains("is not a Collection")) { // 转换变量类型并重试 variables.put("handleDepts", convertToCollection(variables.get("handleDepts"))); taskService.complete(taskId, variables); } else { throw e; } } ``` ### 调试建议 1. **打印变量类型**:在设置变量前后打印类型: ```java System.out.println("handleDepts type: " + handleDepts.getClass().getName()); ``` 2. **查询历史变量**:使用`HistoryService`检查变量存储的实际类型: ```java HistoricVariableInstance variable = historyService.createHistoricVariableInstanceQuery() .variableName("handleDepts") .singleResult(); System.out.println("Stored type: " + variable.getVariableTypeName()); ``` 3. **启用调试日志**:在`log4j.properties`中: ```properties log4j.logger.org.activiti=DEBUG ``` ### 预防措施 1. **统一变量设置工具类**: ```java public class VariableUtils { public static void setCollectionVariable(RuntimeService runtimeService, String executionId, String varName, Object value) { if (value instanceof String) { value = Arrays.asList(((String) value).split(",")); } runtimeService.setVariable(executionId, varName, value); } } ``` 2. **流程文档**:在流程定义文档中明确每个变量的类型要求。 3. **单元测试**:测试变量设置: ```java @Test public void testHandleDeptsVariable() { Map<String, Object> vars = new HashMap<>(); vars.put("handleDepts", Arrays.asList("dept1", "dept2")); runtimeService.startProcessInstanceByKey("processKey", vars); // 验证流程是否正常运行到下一个节点 } ``` ### 相关Activiti文档 - 官方文档:变量类型[^1] - 任务分配规则[^2] 通过以上步骤,我们可以解决`Variable handleDepts is not a Collection`错误,并确保在流程中正确使用集合类型的变量。 §§相关问题§§ 1. 如何在Activiti中自定义变量序列化机制? 2. Activiti排他网关的条件表达式有哪些使用限制? 3. 如何优化Activiti历史变量的存储性能?</think>## Activiti `IllegalArgumentException: Variable handleDepts is not a Collection` 原因分析与解决方案 ### 问题原因分析 在Activiti流程引擎中出现此错误,通常是由于以下原因: 1. **变量类型不匹配**: - 流程定义或服务任务中期望`handleDepts`变量是集合类型(如List、Set) - 实际传入的变量是字符串或其他非集合类型 - 常见于多实例任务(会签)或网关条件判断场景 2. **错误使用场景**: ```java // 错误示例:传入字符串而非集合 taskService.setVariable(taskId, "handleDepts", "dept1,dept2"); // 正确示例:应传入集合 List<String> depts = Arrays.asList("dept1", "dept2"); taskService.setVariable(taskId, "handleDepts", depts); ``` 3. **流程定义要求**(以多实例任务为例): ```xml <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="${handleDepts}" <!-- 此处要求集合类型 --> activiti:elementVariable="dept"> ... </multiInstanceLoopCharacteristics> ``` ### 完整解决方案 #### 1. 确保变量类型正确(推荐) ```java // 使用集合类型存储部门信息 List<String> handleDepts = new ArrayList<>(); handleDepts.add("deptA"); handleDepts.add("deptB"); // 设置流程变量 runtimeService.setVariable(executionId, "handleDepts", handleDepts); ``` #### 2. 类型转换工具方法 ```java public class ActivitiVariableUtils { public static Collection<String> convertToCollection(Object value) { if (value instanceof Collection) { return (Collection<String>) value; } else if (value instanceof String) { return Arrays.asList(((String) value).split(",")); } throw new IllegalArgumentException("无法转换的类型: " + value.getClass()); } } // 使用示例 Object rawValue = runtimeService.getVariable(executionId, "handleDepts"); Collection<String> depts = ActivitiVariableUtils.convertToCollection(rawValue); ``` #### 3. 流程启动时验证变量 ```java public void startProcessWithDepts(String processKey, List<String> depts) { if (depts == null || depts.isEmpty()) { throw new ActivitiException("handleDepts不能为空"); } Map<String, Object> variables = new HashMap<>(); variables.put("handleDepts", depts); runtimeService.startProcessInstanceByKey(processKey, variables); } ``` #### 4. 网关条件处理 当在排他网关中使用集合变量时: ```java // 网关条件表达式示例 execution.setVariable( "condition1", handleDepts.contains("deptA") // 要求handleDepts必须是集合 ); ``` #### 5. 历史变量查询修复 当使用历史变量查询时: ```java historyService.createHistoricVariableInstanceQuery() .variableName("handleDepts") .list() .forEach(var -> { // 类型安全获取 if (var.getValue() instanceof Collection) { Collection<?> depts = (Collection<?>) var.getValue(); } }); ``` ### 调试与验证方法 1. **检查变量类型**: ```java Object variable = runtimeService.getVariable(executionId, "handleDepts"); System.out.println("变量实际类型: " + (variable != null ? variable.getClass() : "null")); ``` 2. **单元测试**: ```java @Test public void testHandleDeptsVariable() { // 模拟流程启动 ProcessInstance instance = runtimeService.startProcessInstanceByKey( "deptProcess", Variables.putValue("handleDepts", Arrays.asList("dept1", "dept2")) ); // 验证变量类型 Object variable = runtimeService.getVariable(instance.getId(), "handleDepts"); assertTrue(variable instanceof Collection); } ``` 3. **流程设计器配置检查**: - 在BPMN设计器中确认多实例配置的`activiti:collection`属性 - 检查所有使用`${handleDepts}`的表达式 ### 最佳实践建议 1. **变量类型标准化**: ```java public static final String VAR_HANDLE_DEPTS = "handleDepts"; public void setHandleDepts(Collection<String> depts) { runtimeService.setVariable(executionId, VAR_HANDLE_DEPTS, depts); } ``` 2. **使用DTO对象封装**: ```java public class DeptInfoDTO { private Collection<String> handleDepts; // getters/setters } // 设置变量 DeptInfoDTO deptInfo = new DeptInfoDTO(); deptInfo.setHandleDepts(Arrays.asList("deptA", "deptB")); runtimeService.setVariable(executionId, "deptInfo", deptInfo); ``` 3. **流程文档注释**: ```xml <process id="deptProcess"> <!-- handleDepts变量要求: Type: java.util.Collection<String> Desc: 需要处理的部门列表 --> </process> ``` ### 总结关键点 - **根本原因**:类型不匹配(期望集合但收到非集合类型) - **修复核心**:确保`handleDepts`始终作为集合传递 - **预防措施**:封装变量操作方法、添加类型验证、完善文档 通过以上方法可彻底解决`Variable handleDepts is not a Collection`错误,并建立健壮的变量处理机制[^1][^2]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值