2016-08-01 339 views
2

注意:这些都是使用当前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。它看起来非常相似,但我不认为我想要在资源文件夹中生成这些文件,这就是自我回答似乎围绕着这些文件的内容。

+1

你最好的计划可能会列入*在你的方法'loadKieBase'负载和编译代码的所有* DRL文件。您所得到的错误表明,声明全局记录器的DRL不包含在该KieBase的构建中 - 因此请确保(通过显式调用写入KIE文件系统)确定它是。 – laune

+0

感谢您的评论。目前,我只有1个测试“子文件夹”和1个规则文件。我很肯定会加载哪个,并在调用kieFileSystem.write()方法时使用。我能不能错过编译组件,或者类似的东西?它似乎没有在任何地方记录任何错误,即使我已经完成所有设置。你似乎也是[这个答案](http://stackoverflow.com/a/24570355/5347955)的作者,这似乎是我也试过的方法,所以真的,为什么这个加载出错了,除了DRL文件编译问题? – Xheory

+0

我在“此答案”中列出的方法有效,它会告诉您DRL中是否有任何错误。当然,你总是有可能犯了另一个错误。 - 要了解此文件或该文件的DRL是否已正确加载,请在每个DRL文件中使用一条规则:“Rule”in DRL x.drl“when System.out.println(...); end'。 – laune

回答