第一章歡迎
我總是和終端業務使用者争論不休,了解規則和流程、最新規則和事件處理的差別。對此,在他們的意識中有這樣的問題,并且他們希望使用某些軟體模拟它。使用兩個供應商提供的傳統方式,強迫業務使用者與一個剛剛獲得方式的面向流程或面向規則的方法一起工作,他們将使用該工具模拟這點,往往整體是極為混亂的。
PegaSystems和Microsoft做了大量的工作,顯示兩者可以被結合,并且可以使用一個行為的模拟方法。這讓業務使用者更自然地應用提供給他們的各種方法工作,不必使用獲得方式的工具。從面向流程到面向規則或中間的灰色地帶——任何當時的相應問題被模拟。
Drools5.0更進了一步,不僅增加了基于工作流與Drools流的BPMN2,而且增加了事件處理與DroolsFusion(熔合),為軟體開發者建立了一個更全面的方法。此處的術語“全面的”被用來強調整體和它局部間的互相依賴性的重要性。
Drools5.0現在被劃分為5個子產品,每個都自帶手冊——Guvnor(BRMS/BPMS),Expert(Rules),Fusion(CEP),Flow(Process/Workflow)和Planner。Guvnor是我們的基于網頁的管理系統,在規則世界中傳統提及的,如一個BRMS(商業規則管理系統)。我們決定抛棄一個擔當管理工作的BRMS術語,因為它不是規則的細節。Expert是傳統的規則引擎。Fusion是事件處理邊,它擔當資料/傳感器的熔合術語。Flow是我們的工作流子產品,由KrisVerlaenen上司,已經做了一些了不起的工作;他正把流與jBPM5合成一體。第5個子產品是Planner,由GeoffreyDeSmet撰寫,解決配置設定和排程類型的問題。雖然還處在開發的初期階段,但已顯示了許多期望。我們希望為2011版增加Semantics(語義),基于描述邏輯,并讓它擔當下一代Drools引擎的一部分。
我一直工作在規則領域,現在大約7年了。我終于感覺到我緊握東西,想法開始成形,并且真正的創新開始出現。對我來說,感覺就象我确實知道我們現在将做什麼,與過去相比,有許多瘋狂的猜想和探索。我與EdsonTirelli和DavideSottara一起努力工作在DroolsExpert設計文檔上。我邀請你閱讀文檔和參與http://community.jboss.org/wiki/DroolsLanguageEnhancements。該文檔帶有東西給下一級,推動Drools成為一個混合的引擎,不僅是一個有能力生産規則的系統,而且混合了邏輯程式設計(prolog)與功能程式設計,以及帶有其他想法的更有表現力和現代感語言的描述邏輯。
我希望你能感覺到我們的團隊和我在Drools上工作的熱情,希望在你的冒險期間能感染你。
MarkProctor(Drools建立者和上司)
第二章Drools發行說明
2.1在Drools5.1.0中,值得注意的新東西。
2.1.1DroolsAPI
如在Drools5.0中一樣,仍然可以使用配置配置一個KnowledgeBase(知識庫),通過一個xml改變集合(changeset),而不是程式設計方式。然而,現在的change-set命名空間被版本化了。這意味着,在Drools5.1.0中,1.0.0xsd應該被引用。
例子2.1下面是一個簡單的版本1.0.0改變集合
<change-setxmlns='http://drools.org/drools-5.0/change-set'
xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
xs:schemaLocation='http://drools.org/drools-5.0/change-setchange-set-5.0.xsdhttp://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd'>
<add>
<resourcesource='classpath:org/domain/someRules.drl'type='DRL'/>
<resourcesource='classpath:org/domain/aFlow.drf'type='DRF'/>
</add>
</change-set>
2.1.2核心
2.1.2.1JMX監控
JMX監控被添加來支援知識庫監控。這尤其重要,象一個常需要事件處理的長期運作流程。初始化整合JOPR也被添加。JMX可以被啟用,使用屬性設定知識庫:
drools.mbeans=<enabled|disabled>或者這個選項在運作時啟用:
kbaseConf.setOption(MBeansOption.ENABLED)
2.1.2.2Spring
Drools現在有擴充的Spring支援,XSD可以在drools-springjar中發現。命名空間為"http://drools.org/schema/drools-spring"。
例子2.2知識庫建構器例子
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:drools="http://drools.org/schema/drools-spring"
xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://drools.org/schema/drools-springhttp://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-container/drools-spring/src/main/resources/org/drools/container/spring/drools-spring-1.0.0.xsd
http://camel.apache.org/schema/springhttp://camel.apache.org/schema/spring/camel-spring.xsd">
<drools:resourceid="resource1"type="DRL"source="classpath:org/drools/container/spring/testSpring.drl"/>
<drools:kbaseid="kbase1">
<drools:resources>
<drools:resourcetype="DRL"source="classpath:org/drools/container/spring/testSpring.drl"/>
<drools:resourceref="resource1"/>
<drools:resourcesource="classpath:org/drools/container/spring/IntegrationExampleTest.xls"type="DTABLE">
<drools:decisiontable-confinput-type="XLS"worksheet-name="Tables_2"/>
</drools:resource>
</drools:resources>
<drools:configuration>
<drools:mbeansenabled="true"/>
<drools:event-processing-modemode="STREAM"/>
</drools:configuration>
</drools:kbase>
</beans>
知識庫接受下面的配置:"advanced-process-rule-integration,multithread,mbeans,event-processing-mode,accumulate-functions,evaluatorsandassert-behavior"。
根據kbase參考可以建立ksessions
例子2.3知識會話
<drools:ksessionid="ksession1"type="stateless"name="stateless1"kbase="kbase1"/>
<drools:ksessionid="ksession2"type="stateful"kbase="kbase1"/>
象知識庫的知識會話可以接受一些配置,包括"work-item-handlers,"keep-references","clock-type","jpa-persistence"。
例子2.4知識會話的配置
<drools:ksessionid="ksession1"type="stateful"kbase="kbase1">
<drools:configuration>
<drools:work-item-handlers>
<drools:work-item-handlername="handlername"ref="handlerid"/>
</drools:work-item-handlers>
<drools:keep-referenceenabled="true"/>
<drools:clock-typetype="REALTIME"/>
</drools:configuration>
</drools:ksession>
StatefulKnowledgeSessions(有狀态知識會話)可以被配置為JPA持久化
例子2.5JPA配置用于StatefulKnowledgeSessions
<beanid="ds"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<propertyname="driverClassName"value="org.h2.Driver"/>
<propertyname="url"value="jdbc:h2:tcp://localhost/DroolsFlow"/>
<propertyname="username"value="sa"/>
<propertyname="password"value=""/>
</bean>
<beanid="myEmf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<propertyname="dataSource"ref="ds"/>
<propertyname="persistenceUnitName"value="org.drools.persistence.jpa.local"/>
</bean>
<beanid="txManager"class="org.springframework.orm.jpa.JpaTransactionManager">
<propertyname="entityManagerFactory"ref="myEmf"/>
</bean>
<drools:ksessionid="jpaSingleSessionCommandService"type="stateful"kbase="kbase1">
<drools:configuration>
<drools:jpa-persistence>
<drools:transaction-managerref="txManager"/>
<drools:entity-manager-factoryref="myEmf"/>
<drools:variable-persisters>
<drools:persisterfor-class="javax.persistence.Entity"implementation="org.drools.persistence.processinstance.persisters.JPAVariablePersister"/>
<drools:persisterfor-class="java.lang.String"implementation="org.drools.container.spring.beans.persistence.StringVariablePersister"/>
<drools:persisterfor-class="java.io.Serializable"implementation="org.drools.persistence.processinstance.persisters.SerializableVariablePersister"/>
</drools:variable-persisters>
</drools:jpa-persistence>
</drools:configuration>
</drools:ksession>
知識庫會話可以支援啟動批處理腳本,前面的版本使用"script"元素名,它将被更新為"batch"。下面的指令被支援:"insert-object","set-global","fire-all-rules","fire-until-halt","start-process","signal-event"。可以使用匿名Bean或命名"ref"屬性。
例子2.6啟動批處理指令
<drools:ksessionid="jpaSingleSessionCommandService"type="stateful"kbase="kbase1">
<drools:script>
<drools:insert-objectref="person1"/>
<drools:start-processprocess-id="procname">
<drools:parameteridentifier="varName"ref="varRef"/>
</drools:start-process>
<drools:fire-all-rules/>
</drools:script>
</drools:ksession>
在Spring中支援執行節點(ExecutionNodes),它們提供了一個注冊的ksessions。它可以與Camel一起提供ksessions路由。
2.1.2.3Camel
Spring可以與Camel組合,提供聲明式規則服務。一個Camel政策從Drools被添加,Drools提供魔法注入類加載器(ClassLoader),類加載器被ksession用于任何資料的格式化,它還增強了JAXB和XStream資料的格式化。假如在Jaxb情況下,它添加另外的Drools路徑資訊,利用XStream注冊Drools相關聯的轉換器,并取别名。
你可以使用不同的位址,建立你需要的盡可能多的端點。需要CommandMessagBodyReader配置設定有效負荷給Camel處理。
例子2.8Rest端點配置
<cxf:rsServerid="rsServer"
address="/kservice/rest"
serviceClass="org.drools.jax.rs.CommandExecutorImpl">
<cxf:providers>
<beanclass="org.drools.jax.rs.CommandMessageBodyReader"/>
</cxf:providers>
</cxf:rsServer>
然後,Camel路由可以連接配接到CXF端點,允許你控制如資料的格式化和根據Droolsksessions執行等事情的有效負荷。Drools政策增加某些智能給路由。如果使用JAXB或XStream,它将注入定制路徑和轉換器,它也可以在伺服器邊設定類加載器,基于目标ksessions的。在客戶邊,它自動解包Response(響應)對象。
這個例子使用了一個增強的XStream的資料格式解組有效負荷,并且根據ksession1執行個體執行它。"node"在這兒引用了ExecutionContext(執行上下文),它是一個注冊的ksessions上下文。
例子2.9Camel路由
<beanid="droolsPolicy"class="org.drools.camel.component.DroolsPolicy"/>
<camelContextid="camel"xmlns="http://camel.apache.org/schema/spring">
<route>
<fromuri="cxfrs://bean://rsServer"/>
<policyref="droolsPolicy">
<unmarshalref="xstream"/>
<touri="drools://node/ksession1"/>
<marshalref="xstream"/>
</policy>
</route>
</camelContext>
Drools端點"drools:node/ksession1",由執行節點名字、分隔符和可選的知識會話名字構成。如果知識會話沒有指定路由,會查找在輸入的有效負荷的執行個體中的"lookup"屬性,或者在頭部屬性"DroolsLookup"中去查找。
2.1.2.4Drools伺服器
Spring,Camel和CXF可以被組合,用于聲明式服務,drools-server是一個.war,組合了它們與某些開箱即用的例子xml,就像一類模闆。如果你正在jboss容器中使用war,,那麼你需要添加這個元件,http://camel.apache.org/camel-jboss.html。該war包含了一個test.jsp,顯示一個象你開始的例子一樣的回顯。這個例子隻是執行一個簡單的"echo"類型的應用程式。它發送一個消息到規則伺服器,規則伺服器預先增加單詞"echo"到開頭,并發送它回去。預設時,消息是"HelloWorld",使用url參數msg——test.jsp?msg="MyCustomMessage",可以傳遞不同的消息。
2.1.2.5知識代理增量變化支援
新版的知識庫代理在它配置中支援newInstance=false(增量變化集合建構)。
當設定這個屬性為false,知識庫代理使用存在的知識庫參考應用增量變化。現在知識庫代理可以用增量的方式處理監控的資源更改。更改的定義被編譯,并和原始版本比較。根據定義的類型,以不同的方式表現:
l Rules:用于規則,代理搜尋在它的屬性中的更改,左手邊和右手邊。
l Queries:查詢總在kbase上被替代,無論它們被更改還是沒有被更改。
l 其他定義:所有其他定義總是在kbase中被替代(隻要它們被更改)。我們希望在将來的版本中,為更改定義的探測增加更好的支援。
目前的實作隻支援規則、查詢和函數定義的探測。類型聲明不能被探測。
2.1.2.6會話檢查與報告架構
一個用于運作時會話檢查與報告的基于架構的新的API被引入,進而更好地在調試或應用程式成型時采集資料。這個檢查架構将成為加工功能的基礎,用來幫助為每個會話的内容提供更詳細的資訊。這個api是實驗性的,并不是用在drools-api中,但可自由的使用,并幫助我們改進它。
要檢查一個會話,可以使用以下api調用之一:
例子2.10建立一個會話檢查器
StatefulKnowledgeSessionksession=...
//...insertfacts,firerules,etc
SessionInspectorinspector=newSessionInspector(ksession);
StatefulKnowledgeSessionInfoinfo=inspector.getSessionInfo();
StatefulKnowledgeSessionInfo執行個體将包含許多在會話分析期間采集的相關資料。提供了一個簡單的例子報告模闆,并且可以利用下面的api調用産生:
例子2.11産生一個報告
Stringreport=SessionReporter.generateReport("simple",info,null);
2.1.3Expert
2.1.3.1差異更新
傳統Rete算法用retract+assert(撤消+斷言)做一個更新,對一個給定的事實,這導緻所有的局部比對被撤銷,然而,在assert(斷言)期間,其中一些會被再次重建;因為它們在更新前為true,并且在更新後仍然為true。這導緻許多不需要的對象被摧毀,并且這些行為增加了垃圾收集器的負荷。現在的更新是一個單程,并在适當的位置檢查局部比對,避免不必要的局部比對被摧毀。經曆事件和實事維護的一個正規化過程也不再需要;正規化過程是我們準備着眼于激活retract(撤消)的地方,被插入的激活斷定真正被添加的東西,由真正插入的東西确定“差異”。
2.1.3.2Channels(通道)
退出點已經用更合适的名字Channels(通道)替代,我們覺得它更合适,因為多個規則引擎可以使用它們,并且不是切入點的精确對立面。切入點明顯與進入Rete網絡中的一個分區有關聯。
2.1.3.3現場查詢
Doorls一直有一個查詢支援,但結果是以一個可疊代的集合傳回;這使監測随着時間的變化很困難。
我們現在用現場查詢實作它,它與一個偵聽器相連,而不是傳回一個可疊代的集合。這些現實查詢持續打開建立的一個視圖,并且為這個視圖的内容釋出變化事件。是以,你現在可以執行你的查詢,利用參數,并在結果視圖中偵聽變化。
例子2.12實作ViewChangedEventListener
finalListupdated=newArrayList();
finalListremoved=newArrayList();
finalListadded=newArrayList();
ViewChangedEventListenerlistener=newViewChangedEventListener(){
publicvoidrowUpdated(Rowrow){
updated.add(row.get("$price"));
}
publicvoidrowRemoved(Rowrow){
removed.add(row.get("$price"));
}
publicvoidrowAdded(Rowrow){
added.add(row.get("$price"));
}
};
//OpentheLiveQuery
LiveQueryquery=ksession.openLiveQuery("cheeses",newObject[]{"cheddar","stilton"},listener);
...
...
query.dispose()//makesureyoucalldisposewhenyouwantthequerytoclose
一個Doorls部落格文章包含了一個用于現場查詢的Glazed清單內建的例子
http://blog.athico.com/2010/07/glazed-lists-examples-for-drools-live.html(不可用)
[http://planet.jboss.org/view/post.seam;jsessionid=8F25E6F156E3093608A38BDCCE17369C?post=glazed_lists_examples_for_drools_live_querries]
2.1.3.4定時器和月曆
規則現在支援基于interval(間隔)和cron定時器,替代了過時的duration(期限)屬性。
例子2.13定時器屬性使用的例子
timer(int:<initialdelay><repeatinterval>?)
timer(int:30s)
timer(int:30s5m)
timer(cron:<cronexpression>)
timer(cron:*0/15***?)
Interval"int:"定時器遵守JDK語義,初始化延遲,緊跟一個可選的重複間隔。Cron"cron:"定時器遵守标準的cron表達式:
例子2.14一個Cron例子
rule"SendSMSevery15minutes"
timer(cron:*0/15***?)
when
$a:Alarm(on==true)
then
channels["sms"].insert(newSms($a.mobileNumber,"Thealarmisstillon");
end
當規則被引發時,現在可以控制月曆。月曆api是模拟Quartzhttp://www.quartz-scheduler.org/:
例子2.15調節一個Quartz月曆
CalendarweekDayCal=QuartzHelper.quartzCalendarAdapter(org.quartz.CalendarquartzCal)
月曆使用StatefulKnowledgeSession(有狀态知識會話)注冊:
例子2.16注冊一個月曆
ksession.getCalendars().set("weekday",weekDayCal);
它們可以同時用于普通規則和包含定時器的規則中。規則的calendar屬性可以有一個或多個逗點月曆名字:
例子2.17一起使用月曆和定時器
rule"weekdaysarehighpriority"
calendars"weekday"
timer(int:01h)
when
Alarm()
then
send("priorityhigh-wehaveanalarm);
end
rule"weekendarelowpriority"
calendars"weekend"
timer(int:04h)
when
Alarm()
then
send("prioritylow-wehaveanalarm);
end
2.1.3.5決策表(Excel)
2.1.3.5.1簡單模闆,用于單元格内部可變長度逗點分隔的清單
在一個單元格中可以有一個逗點分隔的清單,并且用一個forall模闆可以渲染它們。
例子2.18DTableforall文法
forall(<separator>?){<codesnippt>}
例子2.19DTableforall例子
forall(,){propertyName==$}
forall(&&){propertyName==$}
forall(||){propertyName==$}
forall(||){propertyNameA==$}&&forall(||){propertyNameB==$}
等等
2.1.4Flow
2.1.4.1BPMN2
正如我們早期已宣稱的一樣,Dools團隊已決定支援使用XML指定業務流程的即将到來的BPMN2.0規範。這個裡程碑包含了BPMN2解析器的重大擴充,使用DroolsFlow來支援BPMN2的更多功能。更具體的有:
l 更廣泛的事件支援:更多的事件類型組合(開始、中間、結束)和事件觸發(例如,包括錯誤、更新、定時器、條件、信号事件),以及已包括(中斷和非中斷)邊界事件。
l 子流程參數。
l 發散的綜合性出入口
l 等等
BPMN2已被內建在完整的Dools工具鍊中,支援業務流程的整個生命周期。它包括:
l 能夠與我們的Eclipse工具一起使用BPMN2流程。
l Guvnor作為流程庫。
l 基于網頁的管理,使用BPM控制台。
l 審計和調試。
l 特殊域流程。
l 等等
是以,DroolsFlow不僅是一流的開源流程引擎,天然地支援這樣一個重要的BPMN2結構集合,而且我們的面向知識的方法,也允許你容易組合你的BPMN2流程與業務規則,以及複雜的事件處理,完全使用相同的APIs和工具。
2.1.4.2基于網頁的管理控制台
現在也可以通過一個網頁控制台管理DroolsFlow流程。它包括的功能有:管理你的流程執行個體(開始/停止/檢查),檢查你的(人的)任務清單,執行那些任務,産生報表。
這個控制台實際上是HeikoBraun的工作(卓越的),他建立了一個通用的BMP控制台,可以被用來支援多種流程語言。我們實作了必要的元件,允許這個控制台能與DroolsFlow引擎通信。
2.1.4.3可插式可變持久化
DroolsFlow可以持久化運作流程的運作時間狀态到一個資料庫(是以它們完全不需要在記憶體,并且在故障情況時可以被存儲)。我們的預設持久化機制是用一個二進制對象(利用相關的中繼資料)存儲關聯于一個流程執行個體的所有運作時間資訊。關聯這個流程執行個體(又名流程執行個體變量)的資料也作為這個二進制對象的一部分被存儲。然而這可以産生問題(1)在資料沒有被序列化時,(2)當用流程執行個體狀态的部分持久化,對象太大時,或者(3)在其他地方已經被持久化時。為此,我們實作了可插式可變持久化,使用者可以定義多少變量的值被存儲。例如,它允許你存儲個别變量的值,并且支援JPA實體被分别存儲和引用(避免狀态重複)。
2.1.4.4改進的流程執行個體移植
随着時間的推移,流程可以進化。每當一個流程更新,确定已經運作的流程執行個體會發生什麼是重要的。我們改進了我們的支援,用于移植運作的流程執行個體到流程定義的一個新版本。更多資訊請看DroolsFlow文檔。
2.1.4.5安裝腳本
Drools建構輸出了一個安裝器,它簡化了Guvnor和gwt-控制台的Eclipse插件的安裝。它建立了和複制了需要的jars和war,并且布置它們到JBossAS。它也包含了一個簡單的求值流程例子,你可以用它測試你的安裝。更多資訊,下載下傳Drools安裝器,請看其内部的自述檔案readme。
2.1.5Guvnor
外觀已被清潔,例如少了彈出視窗。意味着用斷言和有關行為發生的資訊更改之後的節省,以及如果出錯時,更好的錯誤報告。
2.1.5.3讨論
注釋是在下面的“文檔”部分(當然是可選的)(并且有一個Atom供應給它們)
圖2.1實時讨論
一個"backchannel(反向通道)"類型連接配接,保持了對浏覽器的開放,允許消息推回——這意味着(在啟用時)資訊實時顯示(和其他便利的事情一樣,如果某東西添加到一個清單——清單就會被更新)
2.1.5.4收件箱
收件箱功能提供了這樣的能力,跟蹤你打開或編輯的東西——這顯示在主導航器中的"Inbox"項目下。
圖2.2收件箱分類
l 最近打開的
點選recentlyopened條目,會打開“最近”打開過的所有項目的一個清單(它跟蹤最近你看過的數百個項目)。
l 最近編輯的
所有你儲存過的項目,或者注釋,将馬上顯示在這裡。
l 收到的更改
它跟蹤“其他人”對“你”的“最近編輯”清單中的項目所做的更改。當你打開這些項目,那麼它們會從這個清單中删除(但仍然保留在你最近編輯過的清單中)
圖2.3收件箱項目清單。
2.1.5.5批量導入器
Guvnor導入器是一個maven建構工具,遞規你的規則目錄結構,并且建構一個導入檔案,通過import/export管理功能可以手動導入它到Drools-Guvnor網頁界面。
2.1.5.6DroolsDoc
PDF文檔包含了有關包和每個DRL資産(asset)的資訊。DroolsDoc作為知識包可以從"InformationandimportantURLs"下的包視圖(packageview)下載下傳。
2.1.5.7更新為GWT2.0
GWT被更新,使DroolsGuvnor更快。
2.1.5.8安裝選擇器
安裝選擇器允許使用者選擇什麼樣的資産建構,依據:
n 狀态(例如,開發,品質保證等)
n 分類
n 中繼資料
2.1.5.9單資産驗證
隻要是你正在運作的資産(規則流、規則、決策表),就可以驗證。驗證發現諸如在一個規則中的沖突限制或在決策表中的多餘行等問題。
2.1.5.10全局區
儲存在全局區的資産可以被所有包共享。
2.1.5.11快照之間的差異檢查
列出兩個快照之間的變化。
2.1.5.12在一個标簽中檢視多個資産
可以在一個視圖中打開多個資産。所有的資産可以作為一個組被儲存和編輯。
2.1.5.13From/Collect/Accumulate支援
指導編輯器已基本支援From,Accumulate和Collect模式。你可以添加它們中的任何一個結構作為正規模式。新的表達式建構器元件被建立,增加了對嵌套方法調用的一個變量支援。在規則的WHEN部分頂部使用了“加”按鈕,或者使用呈現在每個模式中的新的“在後面增加”按鈕,将打開彈出,添加新的條件元素到你的規則中。在可能元素的清單中的,你會發現三個新的條目:”From”,“FromAccumulate”和“FromCollect”。
當你添加一個新的”From”元素,你會在指導編輯器看到下面這樣圖象的東西。左邊模式的”From”條件元素是一個正規模式。你可以在這裡添加你希望的任何類型的條件元素。右邊部分的”From”模式是一個表達式建構器。
圖2.4來自一個CE建構器
當你在左邊模式中使用“FromCollect”時,你可以選擇“java.util.Collection”,“java.util.List”或“java.util.Set”事實類型。這個事實類型會被自動包含在事實類型清單中。
右邊模式的收集條件元素可以是下面模式之一:
n FactTypePattern(事實類型模式)
n FreeFormExpression(自由表單表達式)
n FromPattern(From模式)
n FromCollectPattern(FromCollect模式)
n FromAccumulatePattern(FromAccumulate模式)
圖2.5來自CollectCE建構器
當使用“FromAccumulate”時,左邊模式可以是任何事實類型模式。這個條件元素的右邊部分被劃分成兩個:
圖2.6來自累積CE建構器
左邊模式可以是任何事實類型模式。這個條件元素的右邊部分被劃分成兩個:
源模式:(在載圖中的,Bed$n)可以是任何事實類型、From、Collect或者Accumulate模式
累積函數:在這裡你可發現一個标簽式面闆,你可以輸入一個累積函數(在截圖中的sum()),或者你可以使用“CustomCode”建立一個線上定制函數。
2.1.5.14規則模闆
規則模闆可以被指導編輯器用于編輯複雜的規則,然後通過一個電子表格的表格資料隐喻輕松地編寫它。替代了一個字段的值,僅是用名為"TemplateKey"辨別它,并且該key可以作為網格中的一個列。每行可以應用規則模闆來産生一個規則。
圖2.7在'WHEN'部分增加了一個TemplateKey。
圖2.8"THEN"部分增加了一個TemplateKey。
圖2.9根據這些TemplateKey填充行。
圖2.10每行産生一個規則
2.1.5.15工作集
在模組化規則時,使用者暴露所有的事實類型,它可能是整個的很小部分。工作集允許相關的事實類型分組在一起,并在編寫規則時,提供一個更易于管理的選擇事實類型的視圖。
圖2.11顯示導入的類型。
圖2.12建立一個動物工作集。
圖2.13沒有使用工作集,所有類型是可見的。
圖2.14選擇動物工作集。
圖2.15可用的類型減少了。
2.1.5.16事實限制
工作集可以與事實限制相結合,提供額外的設計時間驗證。例如,如果你依據某個人的年齡編寫一個規則,在設計時,我們可以分辨有效的範圍,并且使用它來限制作者。事實限制是工作集的一部分,并且在編輯一個規則時,你必然選擇工作集限制,那個你希望用于作為驗證處理部分的限制。
圖2.16選擇字段。
圖2.17選擇字段限制類型.
圖2.18一個範圍選擇的例子。
圖2.19選擇工作集,用于驗證年齡字段。
圖2.205歲是無效的。
2.1.5.17指導規則編輯器
編輯規則變得更明确。編輯器是更小“盒子”,且用一個普通文本編寫更多規則。增加了"contains"關鍵字,現在在綁定變量給限制是更容易了。
2.1.5.17.1模式排序
指導編輯器在lhs和rhs部分支援模式重排序,以及位置插入,新的模式可以以任何順序被插入(并不總是在最後)。
圖2.21上下移動元素。
圖2.22在任何位置插入元素。
2.1.5.18決策表(Guvnor)
增加了關鍵字"in"。
可以移動列,并且新行的位置可以自由選擇。
2.1.6Eclipse
2.1.6.3在大綱視圖中分組規則
現在你可以為議程組使用排序或分組。
圖2.23分組議程組
圖2.24排序議程組
2.1.6.4支援在審計視圖中拖/放檔案。
現在可以拖放日志檔案到審計視圖中。
2.1.7已知的問題
2.1.7.3多線程模式
使用試驗的多線程執行模式存在一個已知的問題,如下面JIRA中描述的一樣
https://jira.jboss.org/browse/JBRULES-2125
2.2 在Drools 5.0.0中值得關注的新東西
2.2.1 Drools API
Drools現在有完善的api/實作分離物,不再面向規則。當我們開始支援其他邏輯形式時,如工作流和事件處理時,這是一個重要的政策。最重要的改變是我們面向知識,而不是面向規則。drools-api子產品提供接口和工廠,并且與以前相比,我們已竭力提供更好的javadocs,帶有一些代碼片段。drools-api還有助于清楚地顯示有意作為一個使用者的api是什麼,隻是一個引擎的api是什麼,而Drools核心和Drools編譯器沒有充分明确這點。你将使用的最普通的接口有:
n org.drools.builder.KnowledgeBuilder
n org.drools.KnowledgeBase
n org.drools.agent.KnowledgeAgent
n org.drools.runtime.StatefulKnowledgeSession
n org.drools.runtime.StatelessKnowledgeSession
工廠類,帶有靜态方法,提供上面接口的執行個體。一個可插式提供者方法被用來允許提供者實作在運作時連接配接工廠。你将最常使用的工廠有:
n org.drools.builder.KnowledgeBuilderFactory
n org.drools.io.ResourceFactory
n org.drools.KnowledgeBaseFactory
n org.drools.agent.KnowledgeAgentFactory
例子2.20 加載一個規則資源的一個典型例子
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newUrlResource( url ), ResourceType.DRL );
if ( kbuilder.hasErrors() ) {
System.err.println( builder.getErrors().toString() );
}
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( builder.getKnowledgePackages() );
StatefulKnowledgeSession ksession = knowledgeBase.newStatefulKnowledgeSession();
ksession.insert( new Fibonacci( 10 ) );
ksession.fireAllRules();
ksession.dispose();
一個典型的加載一個流程資源的例子。注意ResourceType使用相應的資源類型被改變。
例子 2.21一個典型的加載一個流程資源的例子。注意ResourceType使用相應的資源類型被改變。
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newUrlResource( url ),
ResourceType.DRF );
if ( kbuilder.hasErrors() ) {
System.err.println( builder.getErrors().toString() );
}
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( builder.getKnowledgePackages() );
StatefulKnowledgeSession ksession = knowledgeBase.newStatefulKnowledgeSession();
ksession.startProcess( "Buy Order Process" );
ksession.dispose();
'kbuilder','kbase','ksession'是經常使用的變量辨別符,用knowledge的k開頭。
例子 2.22 我們已統一了決策樹如何加載,現在不再需要利用電子表格編譯器預先生成一緻的DRL。
DecisionTableConfiguration dtconf = KnowledgeBuilderFactory.newDecisionTableConfiguration();
dtconf.setInputType( DecisionTableInputType.XLS );
dtconf.setWorksheetName( "Tables_2" );
kbuilder.add( ResourceFactory.newUrlResource( "file://IntegrationExampleTest.xls" ),
ResourceType.DTABLE,
dtconf );
使用配置也可以配置一個KnowledgeBase,通過一個xml更改集,而不是程式設計方式。
例子2.23 一個簡單的更改集例子
<change-set xmlns='http://drools.org/drools-5.0/change-set'
xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
xs:schemaLocation='http://drools.org/drools-5.0/change-set change-set-5.0.xsd' >
<add>
<resource source='classpath:org/domain/someRules.drl' type='DRL' />
<resource source='classpath:org/domain/aFlow.drf' type='DRF' />
</add>
</change-set>
例子 2.24 可以象其他資源類型一樣添加
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newUrlResource( url ),
ResourceType.ChangeSet );
KnowledgeAgent與 RuleAgent相比較,其他較大的變化是輪詢掃描現在是一個服務了。進一步說,是在代理通知與資源監視之間有一個抽象,允許使用其他輪詢機制。
例子 2.25 這些服務目前不再預設啟動,要啟動它們要如下這樣:
ResourceFactory.getResourceChangeNotifierService().start();
ResourceFactory.getResourceChangeScannerService().start();
增加了兩個接口,ResourceChangeNotifier和ResourceChangeMonitor。KnowledgeAgent使用ResourceChangeNotifie實作訂購資源更改通知。通過添加ResourceChangeMonitor通知ResourceChangeNotifie資源改變了。我們現在隻提供一個開箱既用的的螢幕, ResourceChangeScannerService,它輪詢資源的變化。然而,存在有api用于使用者添加自己的螢幕,是以可以使用一個如jms這樣的基于推的螢幕。
ResourceFactory.getResourceChangeNotifierService().addResourceChangeMonitor( myJmsMonitor);
2.2.2 Drools Guvnor
n 新外觀的網頁工具
圖2.25 新外觀
n 網頁基于決策表編輯器
圖2.26網頁基于決策表編輯器
n 內建的場景測試
圖2.27 運作所有場景
圖2.28 運作單個場景
n WebDAV檔案基于接口庫
圖2.29 WebDAV
n 聲明式模拟類型(不使用pojos的類型)
圖2.30 聲明式模拟
它與"declare"語句一起工作——你現在可以在drl本身内聲明類型。然後你可以裝配它們,不必使用pojo(如果你喜歡)。然後這些類型可用于規則庫中。
u 細粒度安全(鎖定通路每包或每分類應用程式)。隻有分類權限的使用者具有有限的UI能力(針對企業使用者)
u 執行伺服器——執行通過XML或JSON通路規則。
u 分類規則允許你為一個分類設定“父規則”。出現在給定分類的任何規則會“繼承”指定的規則——例如,繼承條件/ LHS。分類的基本規則可以在包配置标簽上設定。RHS不被繼承,隻有LHS被繼承。
u 場景運作器檢測無限循環。
u 現在可以設定在指南編輯器中的DSL句子,用于顯示作為一個下接菜單的枚舉、作為一個資料拾取器的資料、作為一個單選框的布爾值,并且使用正規表達式來校驗使用者輸入(在Guvnor中的DSL小飾件)。
u 函數可以使用文本編輯器進行編輯。
u 可以添加對象到全局集合。
u 翻譯為英語,西班牙語,漢語和日語。
2.2.3 Drools Expert
2.2.3.1 非對稱Rete算法實作
不再需要影子代理。影子代理保護引擎免受有關實事的資訊變化的影響,如果發生在引擎控件的外部,它可能不會被修改或撤消。
2.2.3.2 包建構器現在可以建構多個命名空間
你不再需要對一個包命名空間建構一個PackageBuilder 。隻要保持為所有命名空間增加你的DRLs,并且getPackages()為每個使用的命名空間返加一個包數組。
例子 2.26 獲得多個包
Package[] packages = pkgBuilder.getPackages();
2.2.3.3 規則庫連接配接包建構器
現在可以連接配接一個 RuleBase到一個 PackageBuilder,這意味着規則被建構,并且同時被添加到規則庫。PackageBuilder使用現行的RuleBase的Package執行個體作為它的資源,取消了發生在現有方法中的Package創造和融合。
例子 2.27 連接配接規則庫(RuleBase)到包建構器(PackageBuilder)
RuleBase ruleBase = RuleBaseFactory.newRuleBase();
PackageBuilder pkgBuilder = new PackageBuilder( ruleBase, null );
2.2.3.4 有狀态會話的二進制編碼
有狀态會話現在可以儲存,并可在以後的日期中恢複。預加載資料會話現在可以被建立。對使用者對象的持久化可使用可插式政策,例如,hibernate或特征(identity)映射。
2.2.3.5 類型聲明
Drools現在支援一種新的基礎結構,稱為類型聲明。這個結構達到兩個目的:能夠聲明實事中繼資料,以及能夠為規則引擎動态地産生局部的新的事實類型。Guvnor模拟工具在底層使用了它。下面是該結構的一個例子:
例子 2.28 聲明StockTick
declare StockTick
@role( event )
@timestamp( timestampAttr )
companySymbol : String
stockPrice : double
timestampAttr : long
end
2.2.3.6 聲明實事中繼資料
要聲明和關聯事實的中繼資料,隻需要對你想聲明的每個中繼資料ID使用@符号。例子:
例子 2.29 聲明中繼資料
declare StockTick
@role( event )
end
2.2.3.7 觸發Bean産生
要激活動态bean産生,僅為你的類型聲明添加字段和類型。
例子 2.30 聲明Person
declare Person
name : String
age : int
end
2.2.3.8 DSL的改進
一系列DSL的改進被實作,包括一個完善的新解析器,并且能夠為比對的變量聲明比對的掩碼(mask)。例如,它可限定一個電話号碼字段為2位數的國家代碼+ 3位區号+ 8位數字電話号碼,所有連接配接以“ - ”(破折号)連接配接,通過象這樣聲明DSL映射:電話号碼為{number:\d{2}-\d{3}-\d{8}},所有有效的Java正規表達式可以用于變量的掩碼中。
2.2.3.9 fireUntilHalt()
Drools現在支援fireUntilHalt()功能,它以一種被動模式啟動引擎,在那兒規則會被連續引發,直到調用了halt()。這尤其對CEP(complex event processing)場景有用,CEP場景需要俗稱的“活動查詢”。
2.2.3.10 規則庫分區和多線程傳播
Drools ReteOO算法現在支援一個選項,用于以多線程模式啟動規則庫,在那兒Drools ReteOO網絡被劃分為多個部分,然後規則被多個線程并發計算。對通常有幾個獨立規則并發運作的CEP,它也有一個要求,接近實時性能/吞吐量的要求,并且一個計算不能幹擾其他的計算。
2.2.3.11 XSD模式支援
Drools現在支援XSD模式。記住雖然XSD模式以用于Drools類加載器的本地POJO類生成。在包建構器中存在有一個幫助類用于模式的産生。一旦資料模式被生成,你通常使用JAXB資料加載器插入資料。
2.2.3.12 資料加載器
Drools現在支援兩種資料加載器,Smooks和JAXB。Smooks是一個用于ETL的開源資料轉換工具,JAXB是一個标準的Sun資料映射工具。單元測試顯示Smooks和JAXB均可在這裡找到。
2.2.3.13 類型安全配置
在Drools中,除了能夠通過配置檔案配置選項外,也可用系統屬性配置,通過API的 setProperty()方法設定屬性,Drools-API現在支援類型安全配置。我們不希望為每個可能的配置方法增加特殊的方法,有兩個原因:它污染了API,并且每次都有一個新選項增加到Drools,API将不得不改變。而這種方式,我們遵循子產品化,類基于配置,在此處為每個可能的配置,一個新的選項類增加到了API,除了靈活之外,也維持了API的穩定。是以,現在為了設定配置選項,你隻需要使用枚舉或者提供每個選項的工廠。例如,如果你希望為斷言行為"equality" 配置知識庫,并且自動從模式比對中删除特征(identities),你隻需要使用下面的枚舉:
例子2.31 配置
KnowledgeBaseConfiguration config = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
config.setOption( AssertBehaviorOption.EQUALITY );
config.setOption( RemoveIdentitiesOption.YES );
對于選項,我們不需要預定義限制,或者可以假設多個值,提供一個工廠方法。例如,配置alpha值為5,隻使用get()工廠方法:
例子 2.32 配置alpha值
config.setOption( AlphaThresholdOption.get(5) );
正如你所見,為每個不同的可能配置,使用了相同的setOption()方法,然而它們仍然是類型安全的。
2.2.3.14 新的累積函數:collectSet和collectList
有時候,有必要收集來自實事屬性的值的集合或清單,而不是實事本身。在這種情況下,不可能使用collect CE。是以對這種情況,現在Drools有兩個新的累積函數:collectSet用于收集值的集合(即,無重複的值),collectList用于收集值的清單(即,允許重複的值):
例子 2.33 新的累積函數
# collect the set of unique names in the working memory
$names : Set() from accumulate( Person( $n : name, $s : surname ),
collectSet( $n + " " + $s ) )
# collect the list of alarm codes from the alarms in the working memory
$codes : List() from accumulate( Alarm( $c : code, $s : severity ),
collectList( $c + $s ) )
2.2.3.15 用于類型聲明的新中繼資料:@propertyChangeSupport
事實實作了象定義在Javabean(tm)規範中的屬性改變的支援。現在可以注釋,讓引擎注冊自身來偵聽事實屬性的變化。在Drools 4 API的insert()方法中使用的布爾參數已過時,并且不存在于drools-aip子產品中了。
例子 2.34 @propertyChangeSupport
declare Person
@propertyChangeSupport
end
2.2.3.16 批處理器
批處理器允許一個知識會話使用指令腳本,此外,無論是StatelessKnowledgeSession 還是 StatefulKnowledgeSession實作都可以使用CommandFactory建立這個接口指令,且使用"execute" 方法執行,如下所示:
例子 2.35 使用CommandFactory
ksession.execute( CommandFactory.newInsert( person ) );
盡管這樣,你通常會希望執行一個批處理指令,通過組合指令 BatchExecution可以完成它。BatchExecutionResults現在用來處理結果,某些指令可以使用"out"辨別符,用它來添加結果到BatchExecutionResult。現在可以輕松地執行查詢,并把結果添加到BatchExecutionResult。這個結果進一步被限定到這個執行調用,并且通過BatchExecutionResults傳回。
例子 2.36 使用BatchExecutionResult
List<Command> cmds = new ArrayList<Command>();
cmds.add( CommandFactory.newSetGlobal( "list1", new ArrayList(), true ) );
cmds.add( CommandFactory.newInsert( new Person( "jon", 102 ), "person" ) );
cmds.add( CommandFactory.newQuery( "Get People" "getPeople" );
BatchExecutionResults results = ksession.execute( CommandFactory.newBatchExecution( cmds ) );
results.getValue( "list1" ); // returns the ArrayList
results.getValue( "person" ); // returns the inserted fact Person
results.getValue( "Get People" );// returns the query as a QueryResults instance.
End
CommandFactory較長的描述支援的指令,它們所有都可以使用XStream和BatchExecutionHelper進行編碼。可以使用管道組合它們來自動化會話腳本。
例子 2.37 使用PipelineFactory
Action executeResultHandler = PipelineFactory.newExecuteResultHandler();
Action assignResult = PipelineFactory.newAssignObjectAsResult();
assignResult.setReceiver( executeResultHandler );
Transformer outTransformer = PipelineFactory.newXStreamToXmlTransformer( BatchExecutionHelper.newXStreamMarshaller() );
outTransformer.setReceiver( assignResult );
KnowledgeRuntimeCommand batchExecution = PipelineFactory.newBatchExecutor();
batchExecution.setReceiver( outTransformer );
Transformer inTransformer = PipelineFactory.newXStreamFromXmlTransformer( BatchExecutionHelper.newXStreamMarshaller() );
inTransformer.setReceiver( batchExecution );
Pipeline pipeline = PipelineFactory.newStatelessKnowledgeSessionPipeline( ksession );
pipeline.setReceiver( inTransformer );
對一個規則集使用上面所述的,會更新一個Cheese事實的價格,下面給定的xml會插入一個使用了輸出辨別符(out-identifier)的Cheese執行個體。
例子 2.38 更新Cheese實事
<batch-execution>
<insert out-identifier='outStilton'>
<org.drools.Cheese>
<type>stilton</type>
<price>25</price>
<oldPrice>0</oldPrice>
</org.drools.Cheese>
</insert>
</batch-execution>
然後我們會得到BatchExecutionResults:
例子 2.39 更新Cheese實事
<batch-execution-results>
<result identifier='outStilton'>
<org.drools.Cheese>
<type>stilton</type>
<oldPrice>0</oldPrice>
<price>30</price>
</org.drools.Cheese>
</result>
</batch-execution-results>
2.2.3.17 編碼
MarshallerFactory被用來編碼和解碼StatefulKnowledgeSessions。最簡單的,它可以象下面這樣使用:
例子 2.40 使用MarshallerFactory
// ksession is the StatefulKnowledgeSession
// kbase is the KnowledgeBase
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Marshaller marshaller = MarshallerFactory.newMarshaller( kbase );
marshaller.marshall( baos, ksession );
baos.close();
然而,在處理引用的使用者資料時,你需要更有彈性地使用編碼。要達成它,我們有一個ObjectMarshallingStrategy接口。我們提供了兩個實作,但是使用者可以自己實作它。提供的兩個是IdentityMarshallingStrategy和SerializeMarshallingStrategy。預設為SerializeMarshallingStrategy,如上例所示,它隻在一個使用者執行個體上調用Serializable或Externalizable方法。而IdentityMarshallingStrategy為每個使用者對象建立了一個整數id,并存儲它們在一個映射中,該id被寫入到該流中。在解碼時,它隻簡單地檢視IdentityMarshallingStrategy映射,取回該執行個體。這意味着,如果你使用IdentityMarshallingStrategy,它對編碼執行個體的生命周期是有狀态的,并且會建立ids,保持它企圖編碼的所有對象的引用。
例子 2.41 使用IdentityMarshallingStrategy編碼
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Marshaller marshaller = MarshallerFactory.newMarshaller( kbase, new ObjectMarshallingStrategy[] { MarshallerFactory.newIdentityMarshallingStrategy() } );
marshaller.marshall( baos, ksession );
baos.close();
為增加彈性,我們不能想當然地認為單政策更合适,是以我們增加了一個ObjectMarshallingStrategyAcceptor 接口,每個ObjectMarshallingStrategy都有。編碼器有一個政策鍊,并且當它企圖讀或寫一個使用者對象時,它周遊政策,詢問它們是否承擔負責編碼使用者對象。提供了一個實作為ClassFilterAcceptor。它允許使用字元和通匹符比對類名。預設為"*.*",是以在上面使用的IdentityMarshallingStrategy,它有一個預設的"*.*"接收器。然而,比方說,我們希望序列化所有類,一個給定的包除外,這種情況,我們會使用身份查詢,如下所示:
例子 2.42 使用身份查詢
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectMarshallingStrategyAcceptor identityAceceptor = MarshallerFactory.newClassFilterAcceptor( new String[] { "org.domain.pkg1.*" } );
ObjectMarshallingStrategy identityStratetgy = MarshallerFactory.newIdentityMarshallingStrategy( identityAceceptor );
Marshaller marshaller = MarshallerFactory.newMarshaller( kbase, new ObjectMarshallingStrategy[] { identityStratetgy, MarshallerFactory.newSerializeMarshallingStrategy() } );
marshaller.marshall( baos, ksession );
baos.close();
2.2.3.18 知識代理
KnowlegeAgent由 KnowlegeAgentFactory建立。KnowlegeAgent提供自動加載、緩存和重新加載資源,并且根據一個屬性檔案配置它。當KnowlegeBase使用的資源更改時,KnowlegeAgent可以更新或重構KnowlegeBase。通過給定工廠的配置确定KnowlegeAgent的政策,但通常使用基于标準輪詢的拉政策。我們希望增加基于推的更新,并在将來的版本中重構它。下面的例子,建構了一個代理,它根據在路徑字元串中指定的檔案建構了一個新的KnowledgeBase。它會每30秒拉這些檔案,而不是更新存在的一個,因為 "newInstance" 設定為了"true" (然而,目前隻支援"true" 值,并且很難編碼到引擎中)。
例子 2.43 建構一個代理
// Set the interval on the ResourceChangeScannerService if you are to use it and default of 60s is not desirable.
ResourceChangeScannerConfiguration sconf = ResourceFactory.getResourceChangeScannerService().newResourceChangeScannerConfiguration();
sconf.setProperty( "drools.resource.scanner.interval",
"30" ); // set the disk scanning interval to 30s, default is 60s
ResourceFactory.getResourceChangeScannerService().configure( sconf );
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
KnowledgeAgentConfiguration aconf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
aconf.setProperty( "drools.agent.scanDirectories",
"true" ); // we want to scan directories, not just files, turning this on turns on file scanning
aconf.setProperty( "drools.agent.newInstance",
"true" ); // resource changes results in a new instance of the KnowledgeBase being built,
// this cannot currently be set to false for incremental building
KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent( "test agent", // the name of the agent
kbase, // the KnowledgeBase to use, the Agent will also monitor any exist knowledge definitions
aconf );
kagent.applyChangeSet( ResourceFactory.newUrlResource( url ) ); // resource to the change-set xml for the resources to add
KnowledgeAgents可以使用一個空的 KnowledgeBase或植入的一個。如果提供了一個植入的KnowledgeBase,KnowledgeAgent會周遊KnowledgeBase,并訂閱它發現的資源。雖然KnowledgeBuilder可以建構在一個目錄中發現的所有資源,但資訊會被KnowledgeBuilder丢棄,因些那些目錄不會繼續被掃描。隻有作為applyChangeSet(Resource)方法的一部分指定的目錄才會被監控。