Drools 文檔(構建)

介紹

6.0引入了一種新的配置和約定方法來構建知識庫,而不是在5.x中使用編程構建器方法,構建器仍然可使用,由於它用於工具集成。編程

構建如今使用Maven,並與Maven實踐保持一致,KIE項目或模塊只是一個Maven Java項目或模塊,另外還有一個元數據文件META-INF/kmodule.xml,kmodule.xml文件是選擇資源到知識庫並配置這些知識庫和會話的描述符,還有經過Spring和OSGi藍圖提供的XML支持。api

雖然標準Maven能夠構建和打包KIE資源,但它不會在構建時提供驗證,有一個Maven插件,推薦使用它來得到構建時驗證,插件還生成許多類,使運行時加載速度更快。緩存

示例項目佈局和Maven POM描述符在屏幕截圖中進行了說明:session

defaultkiesession.png

KIE使用默認值來最小化配置的數量,一個空的kmodule.xml是最簡單的配置,必須始終有一個kmodule.xml文件,即便是空的,由於它用於發現JAR及其內容。less

Maven能夠經過「mvn install」將一個KieModule部署到本地機器上,本地機器上的全部其餘應用程序都使用它,或者它能夠「mvn deploy」將KieModule推到遠程Maven存儲庫中,構建應用程序將拉取KieModule並在過程當中填充本地Maven存儲庫。dom

maven.png

JAR能夠以兩種方式部署,要麼像Maven依賴項清單中的其餘JAR同樣添加到類路徑,要麼在運行時動態加載它們,KIE將掃描類路徑以找到全部包含kmodule.xml的jar文件,每一個發現的JAR都由KieModule接口表示。術語類路徑KieModule和動態KieModule用於引用這兩種加載方法,雖然動態模塊支持並行版本控制,可是類路徑模塊不支持,此外,一旦模塊在類路徑上,就不能動態加載其餘版本。maven

API的詳細參考資料將包含在下一節中,沒有耐心的人能夠直接跳轉到示例部分,這對於不一樣的用例來講是至關容易理解的。ide

構建

builder.png

建立和構建一個Kie項目

Kie項目具備普通Maven項目的結構,惟一的特色是包含kmodule.xml文件,以聲明的方式定義能夠從中建立的KieBaseKieSession,這個文件必須放在Maven項目的resources/META-INF文件夾中,而全部其餘Kie工件,如DRL或Excel文件,必須存儲在resources文件夾中或其下的任何其餘子文件夾中。函數

因爲全部配置方面都提供了有意義的默認值,因此最簡單的kmodule.xml文件能夠僅包含一個空的kmodule標記,以下所示:工具

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule"/>

這樣,kmodule將包含一個默認的KieBase,存儲在resources文件夾或其任何子文件夾下的全部Kie資源都將被編譯並添加到其中,爲了觸發這些工件的構建,爲它們建立一個KieContainer就足夠了。

KieContainer.png

對於這個簡單的例子,建立一個KieContainer就足夠了,它能夠讀取從類路徑構建的文件:

KieServices kieServices = KieServices.Factory.get();
KieContainer kContainer = kieServices.getKieClasspathContainer();

KieServices是一個能夠訪問全部Kie構建和運行時設施的接口:

KieServices.png

經過這種方式,全部Java源和Kie資源都被編譯並部署到KieContainer中,而KieContainer使其內容在運行時可用。

kmodule.xml文件

如前一節所述,kmodule.xml文件是能夠聲明地配置能夠從KIE項目建立的KieBaseKieSession的地方。

特別是KieBase是應用程序全部知識定義的存儲庫,它將包含規則、流程、函數和類型模型。KieBase自己不包含數據,相反,會話是從KieBase建立的,KieBase中能夠插入數據,從KieBase中能夠啓動流程實例。建立KieBase可能很重,而建立會話很是輕,所以建議在可能的狀況下緩存KieBase,以容許重複建立會話。然而,終端用戶一般沒必要擔憂,由於KieContainer已經自動提供了這種緩存機制。

KieBase.png

相反,KieSession存儲並在運行時數據上執行,它是由KieBase建立的,若是在kmodule.xml文件中定義了它,則更容易從KieContainer直接建立。

KieSession.png

kmodule.xml容許定義和配置一個或多個KieBase,併爲每一個KieBase建立全部不一樣的KieSession,以下面的示例所示:

<kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.drools.org/xsd/kmodule">
  <configuration>
    <property key="drools.evaluator.supersetOf" value="org.mycompany.SupersetOfEvaluatorDefinition"/>
  </configuration>
  <kbase name="KBase1" default="true" eventProcessingMode="cloud" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg1">
    <ksession name="KSession2_1" type="stateful" default="true"/>
    <ksession name="KSession2_2" type="stateless" default="false" beliefSystem="jtms"/>
  </kbase>
  <kbase name="KBase2" default="false" eventProcessingMode="stream" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg2, org.domain.pkg3" includes="KBase1">
    <ksession name="KSession3_1" type="stateful" default="false" clockType="realtime">
      <fileLogger file="drools.log" threaded="true" interval="10"/>
      <workItemHandlers>
        <workItemHandler name="name" type="org.domain.WorkItemHandler"/>
      </workItemHandlers>
      <listeners>
        <ruleRuntimeEventListener type="org.domain.RuleRuntimeListener"/>
        <agendaEventListener type="org.domain.FirstAgendaListener"/>
        <agendaEventListener type="org.domain.SecondAgendaListener"/>
        <processEventListener type="org.domain.ProcessListener"/>
      </listeners>
    </ksession>
  </kbase>
</kmodule>

在這裏的標籤包含一個鍵-值對列表,這些鍵-值對是用於配置KieBase構建過程的可選屬性,例如,這個樣例kmodule.xml文件定義了一個額外的自定義操做符,名爲supersetOf,並由org.mycompany.SupersetOfEvaluatorDefinition類實現。

在定義了這兩個KieBase以後,就能夠從第一個KieBase中實例化兩個不一樣類型的KieSession,而從第二個KieBase中實例化一個,能夠在kbase標記上定義的屬性列表,以及它們的含義和默認值以下:

屬性名稱 默認值 承認的值 含義
name none 任何值 從KieContainer檢索此KieBase的名稱,這是惟一的強制屬性。
includes none 任何逗號分隔的列表 這個kmodule中包含的其餘KieBase的逗號分隔列表,全部這些KieBase的構件也將包括在這。
packages all 任何逗號分隔的列表 默認狀況下,resources文件夾下的全部Drools構件(任何級別)都包含在KieBase中,此屬性容許將在此KieBase中編譯的構件限制爲僅屬於包列表的構件。
default false true,false 定義這個KieBase是不是這個模塊的默認值,所以能夠從KieContainer建立它,而不向它傳遞任何名稱,每一個模塊中最多能夠有一個默認的KieBase。
equalsBehavior identity identity,equality 定義當一個新事實插入到工做內存中時,Drools的行爲。使用identity,它老是建立一個新的FactHandle,除非同一個對象尚未出如今工做內存中,而只有在新插入的對象與已經存在的事實不相等(根據其相等的方法)時,它才相等。
eventProcessingMode cloud cloud,stream 在雲模式下編譯時,KieBase將事件視爲正常事實,而在流模式下則容許對它們進行時間推理。
declarativeAgenda disabled disabled,enabled 定義聲明性議程是否啓用。

相似地,ksession標籤的全部屬性(固然名字除外)都有有意義的默認值,下表列出並描述了它們:

屬性名稱 默認值 承認的值 含義
name none 任何值 KieSession的惟一名稱,用於從KieContainer提取KieSession,這是惟一的強制屬性。
type stateful stateful,stateless 有狀態會話容許迭代地使用工做內存,而無狀態會話是使用提供的數據集一次性在工做內存中執行。
default false true,false 定義這個KieSession是不是這個模塊的默認值,所以它能夠從KieContainer建立,而無需傳遞任何名稱,在每一個模塊中,每種類型最多能夠有一個默認的KieSession。
clockType realtime realtime,pseudo 定義事件時間戳是由系統時鐘決定仍是由應用程序控制的psuedo時鐘決定,這個時鐘對於時間規則的單元測試特別有用。
beliefSystem simple simple,jtms,defeasible 定義KieSession所使用的信賴系統的類型。

正如前面的kmodule.xml示例所述,還能夠在每一個KieSession上聲明建立一個文件(或控制檯)記錄器、一個或多個WorkItemHandler和一些監聽器,這些監聽器能夠是3種不一樣的類型:ruleRuntimeEventListeneragendaEventListenerprocessEventListener

在定義了相似於前一個示例中的kmodule.xml以後,如今從KieContainer可使用它們的名稱簡單地檢索KieBaseKieSession

KieServices kieServices = KieServices.Factory.get();
KieContainer kContainer = kieServices.getKieClasspathContainer();

KieBase kBase1 = kContainer.getKieBase("KBase1");
KieSession kieSession1 = kContainer.newKieSession("KSession2_1");
StatelessKieSession kieSession2 = kContainer.newStatelessKieSession("KSession2_2");

須要注意的是,因爲KSession2_1KSession2_2屬於兩種不一樣的類型(第一種是有狀態的,而第二種是無狀態的),所以須要根據KieContainer聲明的類型調用兩種不一樣的方法。若是請求KieSessionKieContainer的類型與kmodule.xml文件中聲明的類型不一致,KieContainer將拋出一個RuntimeException。另外,因爲KieBaseKieSession已經被標記爲default,因此在不傳遞任何名字的狀況下,能夠從KieContainer那裏獲得它們。

KieContainer kContainer = ...

KieBase kBase1 = kContainer.getKieBase(); // returns KBase1
KieSession kieSession1 = kContainer.newKieSession(); // returns KSession2_1

因爲Kie項目也是Maven項目,所以在pom.xml文件中聲明的groupId、artifactId和version用於生成一個ReleaseId,用於在應用程序中惟一標識該項目,這容許經過簡單地將ReleaseId傳遞給KieServices來從項目中建立一個新的KieContainer

KieServices kieServices = KieServices.Factory.get();
ReleaseId releaseId = kieServices.newReleaseId( "org.acme", "myartifact", "1.0" );
KieContainer kieContainer = kieServices.newKieContainer( releaseId );

使用Maven構建

Maven的KIE插件確保構件資源獲得驗證和預編譯,建議在任什麼時候候都使用它,要使用該插件,只需將其添加到Maven pom的構建部分。xml並經過使用包裝kjar激活它。要使用該插件,只需將其添加到Maven pom.xml的build部分,並經過使用打包kjar激活它。

<packaging>kjar</packaging>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.kie</groupId>
        <artifactId>kie-maven-plugin</artifactId>
        <version>7.7.0.Final</version>
        <extensions>true</extensions>
      </plugin>
    </plugins>
  </build>

這個插件支持全部Drools/jBPM knowledge資源。可是,若是你在Java類中使用特定的KIE註解,例如@kie.api.Position,你須要在kie-api上添加編譯時依賴到你的項目。咱們建議對全部其餘的KIE依賴項使用提供的做用域,這樣,kjar就會盡量保持輕量級,而不依賴於任何特定的KIE版本。

在不使用Maven插件的狀況下構建KIE模塊將把全部資源複製到生成的JAR中,當運行時加載JAR時,它將嘗試構建全部資源,若是存在編譯問題,它將返回null KieContainer,它還將編譯開銷推到運行時,通常來講,這是不推薦的,並且Maven插件應該老是被使用。

以編程方式定義KieModule

還能夠經過編程方式定義屬於KieModule的KieBaseKieSession,而不是kmodule.xml文件中的聲明性定義。一樣的編程API還容許顯式地添加包含Kie構件的文件,而不是自動從項目的resources文件夾中讀取它們。爲此,有必要建立一個KieFileSystem(一種虛擬文件系統),並將項目中包含的全部資源添加到其中。

KieFileSystem.png

像全部其餘Kie核心組件同樣,你能夠從KieServices得到KieFileSystem的實例,kmodule.xml配置文件必須添加到文件系統中,這是一個強制性的步驟。Kie還提供了一個由KieModuleModel實現的方便的fluent API,以編程方式建立這個文件。

KieModuleModel.png

爲了在實踐中作到這一點,有必要從KieServices中建立一個KieModuleModel,使用所需的KieBaseKieSession配置它,轉換到XML,並將XML添加到KieFileSystem,這個過程以下例所示:

KieServices kieServices = KieServices.Factory.get();
KieModuleModel kieModuleModel = kieServices.newKieModuleModel();

KieBaseModel kieBaseModel1 = kieModuleModel.newKieBaseModel( "KBase1 ")
        .setDefault( true )
        .setEqualsBehavior( EqualityBehaviorOption.EQUALITY )
        .setEventProcessingMode( EventProcessingOption.STREAM );

KieSessionModel ksessionModel1 = kieBaseModel1.newKieSessionModel( "KSession1" )
        .setDefault( true )
        .setType( KieSessionModel.KieSessionType.STATEFUL )
        .setClockType( ClockTypeOption.get("realtime") );

KieFileSystem kfs = kieServices.newKieFileSystem();
kfs.writeKModuleXML(kieModuleModel.toXML());

此時,還須要經過它的fluent API向KieFileSystem添加其餘全部構成項目的Kie構件,這些構件必須添加到相應的Maven項目的相同位置。

KieFileSystem kfs = ...
kfs.write( "src/main/resources/KBase1/ruleSet1.drl", stringContainingAValidDRL )
        .write( "src/main/resources/dtable.xls",
                kieServices.getResources().newInputStreamResource( dtableFileStream ) );

這個示例代表,添加Kie構件能夠同時做爲純字符串和Resource,在後者中,Resource能夠由KieResources工廠建立,也能夠由KieServices提供,KieResources提供了許多方便的工廠方法來將InputStreamURLFile或表示文件系統路徑的String轉換爲能夠由KieFileSystem管理的Resource

KieResources.png

一般,能夠從用於將Resource添加到KieFileSystem的名稱的擴展推斷出資源的類型,可是,也能夠不遵循Kie約定的文件擴展名,並顯式地爲Resource分配特定的ResourceType,以下所示:

KieFileSystem kfs = ...
kfs.write( "src/main/resources/myDrl.txt",
           kieServices.getResources().newInputStreamResource( drlStream )
                      .setResourceType(ResourceType.DRL) );

將全部資源添加到KieFileSystem並經過將KieFileSystem傳遞給KieBuilder來構建它。

KieBuilder.png

當成功構建KieFileSystem的內容時,生成的KieModule會自動添加到KieRepositoryKieRepository是一個單例庫,充當全部可用KieModule的存儲庫。

KieRepository.png

在此以後,就能夠經過KieServicesKieModule建立一個新的KieContainer,使用ReleaseId,可是,由於在這種狀況下,KieFileSystem並不包含任何pom.xml文件(可使用KieFileSystem.writePomXML方法添加xml文件),Kie不能肯定KieModuleReleaseId,並給它賦一個默認值,這個默認的ReleaseId能夠從KieRepository得到,用來識別KieRepository內部的KieModule,下面的示例展現了整個過程。

KieServices kieServices = KieServices.Factory.get();
KieFileSystem kfs = ...
kieServices.newKieBuilder( kfs ).buildAll();
KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());

在這一點上,能夠從這個KieContainer得到KieBase並建立新的KieSession,這與直接從類路徑建立KieContainer的狀況徹底相同。

相關文章
相關標籤/搜索