2016-08-01 36 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

回答