OptaPlanner集成Drools引擎时如何在.drl文件调用Spring Boot Service解决注入为空问题
集成Drools的OptaPlanner项目规则无法获取Spring注入Service问题说明
- 问题适用范围:仅针对与Drools引擎集成的OptaPlanner规划项目,独立Drools工程不适用该场景的排查逻辑
- 项目现状:已在.drl规则文件中编写需要调用Spring托管业务Service的规则,示例规则片段如下:
rule "RuleLimosis" when ViewPatient($RevId:Id,$PatientID:PatientID, PatientID != null) then boolean limosisFlag = viewPatientService.getChecklistLimosis($RevId); System.out.println("empty stomach status: " + limosisFlag); end
- 异常表现:
- 业务Java代码中通过Spring依赖注入拿到的
viewPatientService是正常可用的Bean实例 - 已在Planning Solution类中通过
@ProblemFactProperty注解暴露相关对象,但运行时.drl规则内读取到的viewPatientService值为null,无法完成方法调用
- 业务Java代码中通过Spring依赖注入拿到的
根因与解决方法
- 核心问题:OptaPlanner在构建求解阶段的Working Memory时,只会加载被标记为Problem Fact、Planning Entity的业务域对象;Drools规则运行时不会自动关联Spring容器的Bean实例,直接在规则中引用未被纳入上下文的注入对象,自然会读取到null值。
- 落地解决步骤:
- 不要将Spring托管的Service实例作为普通Problem Fact插入Working Memory——OptaPlanner求解过程会对内存中的Fact做快照克隆,单例Service插入后会破坏求解逻辑稳定性
- 在.drl规则文件头部添加对应全局变量声明,明确规则要引用的外部实例类型:
global com.example.service.ViewPatientService viewPatientService - 在OptaPlanner配置构建KieSession的代码逻辑中,拿到Spring容器托管的
viewPatientService实例后,通过kieSession.setGlobal("viewPatientService", viewPatientService)将实例绑定到规则运行上下文 - 确认全局变量绑定的时机:必须在规则触发、KieSession执行
fireAllRules()之前完成绑定,否则规则运行时依然会读取到未初始化的全局null值 - 如果使用OptaPlanner提供的Spring Boot Starter自动配置KieSession,可通过自定义
KieSessionCustomizerBean的方式完成全局绑定,避免硬编码初始化逻辑
内容的提问来源于stack exchange,提问作者zhang ming
相关产品推荐
相关产品推荐

