将外部DRL文件加载到多个KieBase实例中
注意:这些都是使用当前Kie库的6.4.0.Final实现。将外部DRL文件加载到多个KieBase实例中
嘿那里。我试图用一种方式来使用Drools,我没有在网上找到很多信息(或者我只是在寻找错误的东西,但我已经尝试了几天了),所以我想问一个问题关于我的用例的问题在这里。
我想创建多个KieBase情况下,我认为这就是“水平”我应该在处理此,每一个都有自己的隐蔽的一套在建筑预生成规则,地方不是在资源文件夹 (此时应用程序部署的根文件夹)。因此,如果我有同一个对象A,B或C的多个实例,它们都可以具有不同的属性,因此,每个对象的规则也不相同。
我认为创建一个文件夹,在这种情况下,./rules
与每个事件的子文件夹将是一个整洁的方法在这里。无论何时创建对象,都会在此./rules
文件夹中创建一个相对文件夹。
-
./rules/A/
为对象A. -
./rules/B/
为对象B. -
./rules/C/
为对象C.
然后通过其他方式,我产生这些子文件夹DRL文件,基本上–指正如果我错了–创建包。
现在,当我开始添加的子对象为对象的,我想给./rules/A
文件夹内申请仅规则给他们。
所以我写了下面的类加载,下面网上的例子,我想加载KieBase例如专门装载我添加到某些对象文件夹中的规则文件:
private KieBase loadKieBase(String identifier) {
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
List<String> drlFiles = fileHandler.loadFiles(identifier);
for (String drl : drlFiles) {
String path = "src/main/resources/drools/" + drl;
Resource resource = ResourceFactory.newFileResource(drl);
kieFileSystem.write(path, resource);
}
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
kieBuilder.buildAll();
Results results = kieBuilder.getResults();
if (results.hasMessages(Message.Level.ERROR)) {
...
}
KieContainer kieContainer = kieServices.newKieContainer(kieBuilder.getKieModule().getReleaseId());
KieBaseConfiguration kieBaseConfiguration = kieServices.newKieBaseConfiguration();
KieBase kieBase = kieContainer.newKieBase(kieBaseConfiguration);
return kieBase;
}
记录向我透露资源正在正确加载,这意味着kieFileSystem.write(...)
行获得有效的资源参数。打印加载的文件也会给我提供我想要查看文件的对象的文件。所以这部分全部工作。不过,我得到以下警告:
WARN o.d.c.k.b.impl.AbstractKieModule - No files found for KieBase defaultKieBase
看来确实没有文件被写入到,我在我的资源所做的src/main/resources/drools/
文件夹。我甚至不认为这是必要的–不应该简单地加载到内存中吗?为什么需要再次写入它们,何时可以从它们的预生成文件位置加载它们?
难道这也许是我kmodule.xml
文件是不正确的(而–应我甚至有一个,如果我想基本上使用KieBases内存呢?在我看来,它没有任何意义有这种“物理”参考你在飞行中创建的知识包......)?这是供参考的文件:
<?xml version="1.0" encoding="UTF-8"?>
<kmodule
xmlns="http://jboss.org/kie/6.0.0/kmodule"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<kbase name="KnowledgeBase" packages="drools">
<ksession name="KnowledgeSession"></ksession>
</kbase>
</kmodule>
可能这是正确的,我碰到另一个问题,可能是相关的。
我产生DRL文件使用以下模板的文件的“头”:
package drools
import org.droolstest.TestTicket
global org.slf4j.Logger logger
rule "same-ticket"
...
end
这之后,我尝试使用以下呼叫:
KieBase kieBase = loadKieBase(eventToken);
KieSession kieSession = kieBase.newKieSession();
kieSession.setGlobal("logger", logger);
其中的应用程序崩溃捐赠我这个例外:
INFO o.d.c.k.b.impl.KieRepositoryImpl - KieModule was added: MemoryKieModule[releaseId=org.default:artifact:1.0.0-SNAPSHOT]
INFO c.p.a.c.m.r.RuleGroupClusterModule - KieBase: [email protected]
INFO c.p.a.c.m.r.RuleGroupClusterModule - KieSession: KieSession[0]
Exception in thread "Thread-4" java.lang.RuntimeException: Unexpected global [logger]
at org.drools.core.impl.StatefulKnowledgeSessionImpl.setGlobal(StatefulKnowledgeSessionImpl.java:1162)
这也困惑我。我假设KieBase没有正确加载文件,或类似的东西(这就是为什么我包括这个问题的巨大积累–我很抱歉,这只是我不知道我的问题的根源所在) 。
我发现真的很难包围我的问题可能在这里–除了kmodule.xml
文件,一切似乎都很好,对不对?所以任何形式的帮助将不胜感激! :)
非常感谢!
PS:突然看到类似问题通知我this thread。它看起来非常相似,但我不认为我想要在资源文件夹中生成这些文件,这就是自我回答似乎围绕着这些文件的内容。
我认为你的方式配置kiebase(以编程方式)与kmodule.xml确实存在一些冲突。您是否尝试过编译并运行没有kmodule.xml?最合理的解释是,xml中的kiebase优先于其他。我也认为,这可能是对你有用:
http://planet.jboss.org/post/configuration_and_convention_based_building_and_utilization
你最好的计划可能会列入*在你的方法'loadKieBase'负载和编译代码的所有* DRL文件。您所得到的错误表明,声明全局记录器的DRL不包含在该KieBase的构建中 - 因此请确保(通过显式调用写入KIE文件系统)确定它是。 – laune
感谢您的评论。目前,我只有1个测试“子文件夹”和1个规则文件。我很肯定会加载哪个,并在调用kieFileSystem.write()方法时使用。我能不能错过编译组件,或者类似的东西?它似乎没有在任何地方记录任何错误,即使我已经完成所有设置。你似乎也是[这个答案](http://*.com/a/24570355/5347955)的作者,这似乎是我也试过的方法,所以真的,为什么这个加载出错了,除了DRL文件编译问题? – Xheory
我在“此答案”中列出的方法有效,它会告诉您DRL中是否有任何错误。当然,你总是有可能犯了另一个错误。 - 要了解此文件或该文件的DRL是否已正确加载,请在每个DRL文件中使用一条规则:“Rule”in DRL x.drl“when System.out.println(...); end'。 – laune