JBPM引导决策表中Work Item仅执行一次?如何实现每次触发执行
解决jBPM引导决策表规则仅首次触发WorkItem的问题
这个问题其实是Drools(jBPM基于Drools构建)有状态会话的默认特性导致的,我之前帮朋友排查过类似的场景,下面给你详细解释原因和解决方案:
问题原因
你使用的是有状态会话,这类会话会持续保留当前的事实和规则激活状态。你的规则没有任何when条件,属于“自动触发”的规则——它只会在会话创建后的第一次fire-all-rules时执行一次。一旦规则执行完毕,Drools会移除这个规则的激活记录,后续请求复用同一个会话时,没有新的事实变化触发规则重新激活,所以WorkItem就不会再执行了。这确实是jBPM/Drools的默认行为。
解决方案
这里提供几种不同的方案,你可以根据自己的业务场景选择:
方案1:通过临时触发事实实现重复执行(推荐)
这种方法不需要修改会话类型,只需要调整规则和请求内容,灵活性最高:
- 先定义一个简单的触发类(比如
TriggerWorkItem,不需要任何属性),确保它在KIE容器的类路径中(可以打包到你的业务jar里上传到工作台)。 - 修改你的引导决策表规则,添加匹配这个触发事实的条件:
rule "Row 1 dt1" dialect "mvel" when // 匹配插入的触发事实实例 $trigger : TriggerWorkItem() then org.drools.core.process.instance.WorkItemManager wim = (org.drools.core.process.instance.WorkItemManager) drools.getWorkingMemory().getWorkItemManager(); org.drools.core.process.instance.impl.WorkItemImpl wiQianhaiAddrWorkItemHandler = new org.drools.core.process.instance.impl.WorkItemImpl(); wiQianhaiAddrWorkItemHandler.setName( "QianhaiAddrWorkItemHandler" ); wim.internalExecuteWorkItem( wiQianhaiAddrWorkItemHandler ); // 可选:删除触发事实,避免后续请求中重复匹配(如果每次都插入新实例,也可以省略) drools.retract($trigger); end
- 修改你的请求体,在执行
fire-all-rules之前插入这个触发事实:
{"commands": [ { "insert": {"object": {"class": "com.yourpackage.TriggerWorkItem"}} }, { "fire-all-rules": {} } ]}
每次请求都会插入一个全新的TriggerWorkItem实例,规则会匹配到这个事实并执行WorkItem,完美解决重复触发的问题。
方案2:切换为无状态会话
如果你的业务场景不需要保留任何会话状态,可以将WorkItem Handler配置到无状态会话中。无状态会话每次请求都会创建全新的会话实例,规则会在每次fire-all-rules时重新执行。
- 在工作台设置中,将会话类型调整为无状态。
- 请求端点改为无状态会话的URL(去掉路径中的
/instances):http://localhost:8080/kie-server/services/rest/server/containers/poc2_1.0.1 - 请求体保持原来的
fire-all-rules命令即可。
方案3:每次请求创建新的有状态会话
如果你必须使用有状态会话,但需要每次请求独立执行规则,可以通过KIE Server的API创建新的有状态会话实例:
- 先发送创建会话的请求,获取新的会话ID。
- 使用该会话ID执行
fire-all-rules命令。 - 执行完毕后销毁会话(可选,避免资源浪费)。
不过这种方式会增加会话管理的复杂度,适合需要保持会话状态但每次请求独立的场景。
内容的提问来源于stack exchange,提问作者jm li
相关产品推荐
相关产品推荐

