# 流程参与者获取失败排查与解决手册
当流程卡住、报错“参与者为空”时,请根据您遇到的具体现象,直接查阅下方对应的章节,按照步骤操作。
# 现象一:启动流程或流转时,直接报错“The activity participant is null”
这是最常见的现象,表示引擎在某个环节完全没找到处理人。请根据该环节的参与者配置类型,选择下方对应的排查路径。
# 1. 参与者配置为“角色”、“岗位”、“机构”等组织模型
原因:指定的角色/岗位/机构下没有有效人员,或关联的人员已被禁用。
解决步骤:
确认具体配置:在流程设计器中,找到报错的人工活动,查看其参与者配置的具体对象(例如:角色编码 ROLE_ADMIN)。
SQL排查-角色示例:在数据库中查询该角色下是否有关联的有效人员。
-- 检查角色 'ROLE_ADMIN' 下是否有正常的人员 SELECT r.CODE AS ROLE_CODE, r.NAME AS ROLE_NAME, p.PARTY_ID, -- 判断关联的是人员还是机构 CASE p.PARTY_TYPE WHEN 'emp' THEN (SELECT NAME FROM afc_employee WHERE ID = p.PARTY_ID AND STATUS = 0) WHEN 'org' THEN (SELECT NAME FROM afc_org WHERE ID = p.PARTY_ID AND STATUS = 0) END AS PARTY_NAME FROM afc_role r JOIN afc_r_party_role p ON r.ID = p.ROLE_ID WHERE r.CODE = 'ROLE_ADMIN' -- 替换为您的角色编码 AND r.STATUS = 0; -- 角色本身也要正常- 如果查询结果为空:说明组织模型数据不完整,需要去组织管理模块为该角色添加人员。
- 如果查询结果中的 PARTY_NAME 为 NULL:说明关联的人员或机构已被禁用,需启用或重新关联。
# 2. 参与者配置为“上一环节处理人”
原因:当前环节期望由上一个环节的处理人来处理,但上一个环节可能没有处理人(例如是自动活动),或历史数据被清理。
解决步骤:
查看流程历史:在流程监控中查看该流程实例的历史记录,确认上一个人工环节是否有处理人。
数据兜底:这种配置方式风险较高,强烈建议为此活动配置 “未找到参与者时的处理策略”(见本文档【预防措施】章节),例如转交给流程管理员,防止流程卡死。
# 3. 参与者配置为“业务参与者规则(逻辑流)”
原因:用来获取参与者的逻辑流没有返回正确格式的数据,或逻辑流本身执行报错。
解决步骤:
确认逻辑流位置:该逻辑流必须位于当前应用下,跨应用调用会失败。
调试逻辑流:在逻辑流中添加调试输出,或在代码中打印日志,确认返回值。
检查返回值格式:逻辑流必须返回 WFParticipant 对象或 List<WFParticipant> 列表。
// 正确示例:返回一个人员 import com.eos.workflow.omservice.WFParticipant; def participant = new WFParticipant("12345", "张三", "emp"); // ID, 名称, 类型 context.out = participant; // 正确示例:返回多个人员(用于会签) import com.eos.workflow.omservice.WFParticipant; def participants = []; participants.add(new WFParticipant("12345", "张三", "emp")); participants.add(new WFParticipant("67890", "李四", "emp")); context.out = participants.toArray(); // 注意要转为数组- 错误示例:返回了 null,返回了空列表 [],或返回的 WFParticipant 对象缺少 ID、Name、TypeCode 等必填字段。
# 4. 参与者配置为“自定义 Java 类”
原因:Java 类未加载、类上缺少注解、方法签名错误或返回值格式不对。
解决步骤:
检查类注解:确认 Java 类上有
@ParticipantRuleFunctionClass注解,方法上有@ParticipantRuleFunction注解。检查方法签名:方法入参必须是
(Map<String, Object>, ProcessContext),出参必须是WFParticipant或List<WFParticipant>。检查类加载:
- BPS 应用:确认 jar 包放在
[BPS_HOME]/lib目录下。 - 微服务应用:确认 jar 包通过 maven 依赖引入或放在应用的 lib 目录。
- 排查命令:
# 检查 BPS 启动时是否有类加载异常 grep -i "classnotfound" bps.log | grep -i "您的类名" grep -i "noclassdeffound" bps.log
- BPS 应用:确认 jar 包放在
检查返回值:参考【现象一-第3点】中的返回值格式示例,确保返回的 WFParticipant 对象包含了 ID、Name、TypeCode 等必要信息,且 TypeCode 必须是 emp、org、role 三者之一。
# 现象二:提交表单时指定了后续环节的参与者,但参与者未生效
原因:在提交按钮的返回值中,指定参与者的 JSON 结构错误。
解决步骤:
检查 JSON 结构:确认返回值中
destActivityParticipant为 true,并且destParticipants数组格式正确。// 正确示例:指定下一个环节 manualActivity2 的参与者为张三 return { "destActivity": false, // false 表示按连线走 "links": [{ "id": "manualActivity2", // 目标活动ID "rule": { "destActivityParticipant": true, // 启用参与者指定 "destParticipants": [{ "id": "27", // 参与者ID "name": "张三", // 参与者名称 "typeCode": "emp" // 参与者类型 }] } }] };添加调试代码:在提交按钮的脚本中,用
console.log打印出最终返回的 JSON 字符串,复制到 JSON 在线校验工具中检查格式是否正确。
# 现象三:在组织机构树中搜索员工,提示“无数据”
原因:组织机构树的搜索功能是静态检索,它只过滤当前页面已加载出来的节点。如果目标机构节点没有展开,其下的人员就不会被加载,自然也搜索不到。
解决步骤:
手动展开:先手动点击展开组织机构树,一直展开到可能包含目标人员的机构层级,然后再进行搜索。
代码展开(前端):在页面加载后,自动将树展开到指定层级。
// 示例:页面加载后,将树展开到第3级 setTimeout(() => { const tree = this.Api.getElement('your_tree_component_id'); if (tree) { tree.expandTreeToLevel(3, true); } }, 1000);调用动态检索接口:如果需要真正的全局搜索,需要自行开发后端接口,根据关键字在数据库 afc_user 或 afc_employee 表中进行模糊查询。
# 现象四:调用 API(如 getProbableParticipants)获取参与者时返回空列表
原因:调用 API 时参数不正确,或该活动本身的参与者规则就无法解析出人员。
解决步骤:
检查参数类型:确认
processInstId是 long 类型,activityId是 String 类型。// 正确示例 workFlowManager.getProbableParticipants(12345L, "manualActivity1");验证流程实例和活动:确认
12345L这个流程实例存在,并且"manualActivity1"确实是该流程定义中属于下一步的一个活动 ID。根本原因排查:API 返回空列表只是结果,根本原因还是要回到【现象一】中,根据该活动的参与者配置类型进行排查。
# 预防措施:配置“未找到参与者”兜底策略
为了防止因参与者获取失败导致流程永久卡死,强烈建议为每一个重要的人工活动配置兜底策略。
配置位置:
流程设计器中,选中人工活动节点 -> 属性视图 -> “参与者”选项卡 -> “未找到参与者时的处理策略”。
配置建议:
- 转交给指定人员:选择一个固定的流程管理员或业务主管,作为最后一道防线。这是最推荐的做法。
- 进入异常状态:流程进入“异常”状态,需要管理员登录管理端手动处理。适用于需要严格管控的场景。
- 监控异常:仅记录一条警告日志,流程继续向下流转。此选项风险较高,需谨慎使用。
# 终极排查清单(速查表)
| 步骤 | 检查项 | 一句话操作指引 |
|---|---|---|
| 1 | 看日志 | 搜索 bps.log,关键词 participant、null、activity is null、21040507。 |
| 2 | 定类型 | 确认报错环节的参与者配置类型(角色?逻辑流?自定义类?)。 |
| 3 | 查数据 | 如果是角色/岗位,用 SQL 检查关联关系是否正常,人员是否被禁用。 |
| 4 | 验逻辑 | 如果是逻辑流,确认它在当前应用下,并调试其返回值。 |
| 5 | 验类 | 如果是自定义类,检查注解、方法签名和 jar 包位置。 |
| 6 | 看结构 | 如果是动态指定,用 JSON 校验工具检查提交时的返回值结构。 |
| 7 | 配兜底 | (长期建议) 为活动配置“未找到参与者”的兜底策略。 |