Drools 规则不从 Akka actor 系统触发
Drools rules not firing from Akka actor system
我们在 Scala 中构建了一个 Drools 模块,单独调用时运行良好,但现在我们将其集成到我们构建的 Akka actor 系统中,以便能够通过 REST 调用触发规则。
出于某种原因,任何规则都不会触发,甚至是空白规则,例如:
rule "sample 1"
salience 1000
auto-focus true
when
then
System.out.println("Well, that finally worked!");
end
KieContainer、Session 等似乎没问题,对象(事实)被正确插入(通过检查事实计数验证)。 (KieServices 和 KieContainer 在引导级别初始化,即在创建演员之前,并在稍后阶段使用。)奇怪的是,当 运行 kieSession.fireallrules()
时,触发的规则总数是始终为 0 且事实未更新。
使用 Akka,我们通过 REST 以 JSON 格式发送对象(MyObject 类型)。每个 REST 请求都会创建一个 actor 并调用 Drools 模块,如下所示:
- 创建了一个新演员来调用 Drools 引擎。
- 使用在启动级别设置的 KieServices 创建一个新的 KieSession。 [对于那些看过我以前的帖子的人,是的,以下是 Scala 代码]
val kieSession = DroolsMgt.getKieSession(List("myFile.drl"), Boot.kieServices)
其中 getKieSession
正在调用以下内容:
val kfs = kieServices.newKieFileSystem()
for (filename <- drlFiles) {
val fis = new FileInputStream(filename)
kfs.write(filename, kieServices.getResources.newInputStreamResource(fis))
}
val kieBuilder = kieServices.newKieBuilder(kfs).buildAll()
val kieContainer = kieServices.newKieContainer(kieServices.getRepository.getDefaultReleaseId)
kieContainer.newKieSession()
通过REST接收的对象(从JSON格式中提取)然后通过ksession.insert(testObject)
加载到Drools内存中并保存对象的FactHandle
然后触发规则并使用其 FactHandle 返回更新的对象,如下所示:
ksession.fireAllRules()
val getObject = ksession.getObject(myObjectFH)
ksession.dispose()
getObject.asInstanceOf[MyObject]
和以前一样,这在 运行 Drools 模块单独使用时有效,但在使用上述 actor 系统时无效。我什至尝试触发空规则并将文本打印到屏幕上以进行调试,但实际上没有触发任何规则。我确信我正在调用正确的 DRL 文件和正确的 KieSession 但无法弄清楚这里出了什么问题。 (有什么方法可以检查 KieSession 中的规则数量吗?)
有什么想法吗?
编辑:
在查看 laune 的建议后,我发现没有任何 KiePackages 被加载到 KieBase 中。我已将范围缩小到未作为 KieResources 在 kfs.write("src/main/resources/testFile.drl", kieServices.getResources().newInputStreamResource(fis))
加载的文件
知道是什么原因造成的吗?
作为参考,我正在将 DRL 文件加载到 KieContainer 中并(成功)创建 KieSession,如下所示:
val kieServices = KieServices.Factory.get()
val kfs = kieServices.newKieFileSystem()
val fis = new FileInputStream("src/main/resources/testFile.drl")
kfs.write("src/main/resources/testFile.drl", kieServices.getResources().newInputStreamResource(fis))
val kieBuilder = kieServices.newKieBuilder(kfs).buildAll()
val results = kieBuilder.getResults()
if (results.hasMessages(Message.Level.ERROR)) {
throw new RuntimeException(results.getMessages().toString())
}
val kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId())
kieContainer.newKieSession()
以下代码不会解决您的问题,但它应该可以帮助您诊断您是否确实 运行 您认为的规则和会话。我正在使用 Java 表示法。
KieSession kieSession = ...
KieBase kieBase = kieSession.getKieBase();
Collection<KiePackage> kiePackages = kieBase.getKiePackages();
for( KiePackage kiePackage: kiePackages ){
for( Rule rule: kiePackage.getRules() ){
System.out.println( rule.getName() );
}
}
我们在 Scala 中构建了一个 Drools 模块,单独调用时运行良好,但现在我们将其集成到我们构建的 Akka actor 系统中,以便能够通过 REST 调用触发规则。
出于某种原因,任何规则都不会触发,甚至是空白规则,例如:
rule "sample 1"
salience 1000
auto-focus true
when
then
System.out.println("Well, that finally worked!");
end
KieContainer、Session 等似乎没问题,对象(事实)被正确插入(通过检查事实计数验证)。 (KieServices 和 KieContainer 在引导级别初始化,即在创建演员之前,并在稍后阶段使用。)奇怪的是,当 运行 kieSession.fireallrules()
时,触发的规则总数是始终为 0 且事实未更新。
使用 Akka,我们通过 REST 以 JSON 格式发送对象(MyObject 类型)。每个 REST 请求都会创建一个 actor 并调用 Drools 模块,如下所示:
- 创建了一个新演员来调用 Drools 引擎。
- 使用在启动级别设置的 KieServices 创建一个新的 KieSession。 [对于那些看过我以前的帖子的人,是的,以下是 Scala 代码]
val kieSession = DroolsMgt.getKieSession(List("myFile.drl"), Boot.kieServices)
其中 getKieSession
正在调用以下内容:
val kfs = kieServices.newKieFileSystem()
for (filename <- drlFiles) {
val fis = new FileInputStream(filename)
kfs.write(filename, kieServices.getResources.newInputStreamResource(fis))
}
val kieBuilder = kieServices.newKieBuilder(kfs).buildAll()
val kieContainer = kieServices.newKieContainer(kieServices.getRepository.getDefaultReleaseId)
kieContainer.newKieSession()
通过REST接收的对象(从JSON格式中提取)然后通过
ksession.insert(testObject)
加载到Drools内存中并保存对象的FactHandle然后触发规则并使用其 FactHandle 返回更新的对象,如下所示:
ksession.fireAllRules() val getObject = ksession.getObject(myObjectFH) ksession.dispose() getObject.asInstanceOf[MyObject]
和以前一样,这在 运行 Drools 模块单独使用时有效,但在使用上述 actor 系统时无效。我什至尝试触发空规则并将文本打印到屏幕上以进行调试,但实际上没有触发任何规则。我确信我正在调用正确的 DRL 文件和正确的 KieSession 但无法弄清楚这里出了什么问题。 (有什么方法可以检查 KieSession 中的规则数量吗?)
有什么想法吗?
编辑:
在查看 laune 的建议后,我发现没有任何 KiePackages 被加载到 KieBase 中。我已将范围缩小到未作为 KieResources 在 kfs.write("src/main/resources/testFile.drl", kieServices.getResources().newInputStreamResource(fis))
知道是什么原因造成的吗?
作为参考,我正在将 DRL 文件加载到 KieContainer 中并(成功)创建 KieSession,如下所示:
val kieServices = KieServices.Factory.get()
val kfs = kieServices.newKieFileSystem()
val fis = new FileInputStream("src/main/resources/testFile.drl")
kfs.write("src/main/resources/testFile.drl", kieServices.getResources().newInputStreamResource(fis))
val kieBuilder = kieServices.newKieBuilder(kfs).buildAll()
val results = kieBuilder.getResults()
if (results.hasMessages(Message.Level.ERROR)) {
throw new RuntimeException(results.getMessages().toString())
}
val kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId())
kieContainer.newKieSession()
以下代码不会解决您的问题,但它应该可以帮助您诊断您是否确实 运行 您认为的规则和会话。我正在使用 Java 表示法。
KieSession kieSession = ...
KieBase kieBase = kieSession.getKieBase();
Collection<KiePackage> kiePackages = kieBase.getKiePackages();
for( KiePackage kiePackage: kiePackages ){
for( Rule rule: kiePackage.getRules() ){
System.out.println( rule.getName() );
}
}