Drools 8中如何在BPMN流程的两个Rule Unit间共享DataStore
Drools 8 Rule Unit 跨单元共享 DataStore 实现方案
核心思路
Drools 8 中 Rule Unit 共享 DataStore 的本质是让多个 RuleUnitData 实例引用同一个 DataStore 对象,而非在每个类中单独声明新实例。借助 Quarkus/Kogito 的依赖注入能力,或者手动维护单例对象,就能实现跨单元的数据同步。
具体实现步骤
1. 定义共享数据模型
先确定需要跨单元共享的数据类型,比如示例中的Order对象:
public class Order { private String orderId; private boolean processedByA; // 省略 getter、setter 方法 }
2. 创建全局共享的 DataStore 实例
在 Quarkus 环境下,将 DataStore 封装为应用级单例,确保所有 RuleUnit 都能拿到同一个实例:
import org.drools.core.data.impl.TransactionalDataStore; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class SharedDataStores { private final DataStore<Order> sharedOrderStore = TransactionalDataStore.create(); public DataStore<Order> getSharedOrderStore() { return sharedOrderStore; } }
3. 实现 RuleUnitData 类
让 AUnit 和 BUnit 通过构造注入获取共享的 DataStore,不再在类内部单独声明:
import org.drools.ruleunits.api.DataStore; import org.drools.ruleunits.api.RuleUnitData; import jakarta.inject.Inject; // AUnit 规则单元数据类 public class AUnit implements RuleUnitData { private final DataStore<Order> orders; @Inject public AUnit(SharedDataStores sharedDataStores) { this.orders = sharedDataStores.getSharedOrderStore(); } public DataStore<Order> getOrders() { return orders; } } // BUnit 规则单元数据类 public class BUnit implements RuleUnitData { private final DataStore<Order> orders; @Inject public BUnit(SharedDataStores sharedDataStores) { this.orders = sharedDataStores.getSharedOrderStore(); } public DataStore<Order> getOrders() { return orders; } }
4. 编写规则与执行流程
在 DRL 文件中正常引用各自 RuleUnit 的 DataStore,底层共享实例会自动同步数据:
- AUnit 规则文件(
a-unit.drl):
package com.example.rules; unit AUnit; rule "Mark Order as Processed by A" when $order: Order(processedByA == false) from orders then modify($order) { setProcessedByA(true) }; end
- BUnit 规则文件(
b-unit.drl):
package com.example.rules; unit BUnit; rule "Process Order in B" when $order: Order(processedByA == true) from orders then System.out.println("Order " + $order.getOrderId() + " processed by B"); end
执行流程中,只需向共享 DataStore 插入数据,依次触发 A、B 单元即可:
import jakarta.inject.Inject; import jakarta.enterprise.context.ApplicationScoped; import org.drools.ruleunits.api.RuleUnitProvider; @ApplicationScoped public class RuleExecutor { @Inject private SharedDataStores sharedDataStores; public void executeFlow() { // 插入初始数据到共享DataStore Order order = new Order(); order.setOrderId("ORD-001"); sharedDataStores.getSharedOrderStore().add(order); // 执行A单元规则 RuleUnitProvider.get().createRuleUnitInstance(new AUnit(sharedDataStores)).fire(); // 执行B单元规则 RuleUnitProvider.get().createRuleUnitInstance(new BUnit(sharedDataStores)).fire(); } }
关键注意点
- 优先使用线程安全的 DataStore:Drools 提供的
TransactionalDataStore本身支持线程安全,适合多单元并发场景。 - 禁止在 RuleUnitData 内手动实例化 DataStore:必须保证所有单元引用同一个实例,否则无法实现数据共享。
- 依赖注入简化管理:借助 Quarkus 的
@ApplicationScoped注解,无需手动维护单例生命周期,降低出错概率。
内容的提问来源于stack exchange,提问作者Chaudassin
相关产品推荐
相关产品推荐

