使用Infinispan创建自己的Drools和jBPM持久性
我 在這里發(fā)表的原始文章:
您好,歡迎來到我打算向您展示如何創(chuàng)建自己的Drools和jBPM持久性實現(xiàn)的帖子。 我已經(jīng)為流口水對象開發(fā)了基于infinispan的持久性方案,并且在此過程中學(xué)到了很多東西。 如果您想做某種事情,我打算給您一些指導(dǎo)。
為什么?
如果您正在閱讀本文,那么您可能已經(jīng)有了一個“為什么”來重新定義流口水使用的持久性方案,但是回顧一些很好的理由來做這樣的事情是很好的。 最重要的是,您可能會認(rèn)為出于一個或多個原因,為流口水設(shè)計的JPA持久性方案無法滿足您的需求。 我發(fā)現(xiàn)的一些最常見的是:
給定的模型不足以進(jìn)行我的設(shè)計:為持久化流口水組件(會話,流程實例,工作項等)而創(chuàng)建的當(dāng)前對象當(dāng)前盡可能小,以使數(shù)據(jù)庫具有最佳性能,并且大部分可操作數(shù)據(jù)存儲在映射到Blob對象的字節(jié)數(shù)組中。 這種方案足以使drools和jBPM運行時正常運行,但對于您的域可能還不夠。 您可能希望將運行時信息保存在一種方案中,該方案更易于從外部工具查詢,而這樣做則需要豐富數(shù)據(jù)模型,甚至創(chuàng)建自己的模型。
我正在使用的持久性與JPA不兼容:目前有很多持久性實現(xiàn)不再使用我們曾經(jīng)知道的數(shù)據(jù)庫(分布式緩存,鍵值存儲,NoSQL數(shù)據(jù)庫),并且該模型通常需要額外的映射和特殊功能堅持存放在這樣的倉庫中。 這樣做,有時JPA并不是我們的理想之選
每次加載drools組件時,我都需要從不同的來源加載特殊實體:當(dāng)我們擁有復(fù)雜的對象和/或外部數(shù)據(jù)庫時,有時我們希望新模型以特殊的方式與我們擁有的對象相關(guān)聯(lián)。 也許我們想確保我們的會話以特殊的方式綁定到我們的模型,因為這對我們的業(yè)務(wù)模型有意義。 為此,我們必須更改模型
怎么樣?
為了為我們的會話創(chuàng)建自己的持久性方案,我們需要清楚地了解JPA方案是如何構(gòu)建的,并將其用作構(gòu)建自己的持久性方案的模板。 此類圖顯示了如何實現(xiàn)知識會話的JPA持久性方案:
看起來很復(fù)雜,對吧? 不用擔(dān)心 我們將逐步了解它的工作原理。
首先,您可以看到我們有兩個StatefulKnowledgeSession的實現(xiàn)(或者,如果您使用的是Drools 6,則為KieSession )。 一個完成所有“管腳魔術(shù)”的任務(wù)是StatefulKnoweldgeSessionImpl ,而我們將要使用的任務(wù)是CommandBasedStatefulKnowledgeSession 。 它與持久性無關(guān),但是通過將每個方法調(diào)用都包含在命令對象中并將其執(zhí)行導(dǎo)出到命令服務(wù)中,對持久性有很大幫助。 因此,例如,如果您對這種類型的會話調(diào)用fireAllRules方法,它將創(chuàng)建一個FireAllRulesCommand對象,并將其交給另一個類執(zhí)行。
這種基于命令的實現(xiàn)使我們能夠準(zhǔn)確地完成在drools環(huán)境中實現(xiàn)持久性所需的工作:它使我們能夠在對會話的每次方法調(diào)用之前和之后實現(xiàn)操作。 那就是SingleSessionCommandService的地方
該類很方便:此命令服務(wù)包含一個StatefulKnowledgeSessionImpl和一個PersistenceContextManager。 每次必須執(zhí)行命令時,此類都會創(chuàng)建或加載SessionInfo對象,并告訴持久化上下文將其與StatefulKnowledgeSessionImpl的所有狀態(tài)一起保存。
那是最復(fù)雜的部分:實現(xiàn)會話持久性的部分。 幾乎所有其他內(nèi)容的持久性都可以通過一組給定的接口輕松完成,這些接口提供了一些方法來實現(xiàn)如何加載與會話相關(guān)的所有其他內(nèi)容(流程實例,工作項和信號)。 只要創(chuàng)建一個合適的經(jīng)理及其工廠,就可以委托他們將任何東西存儲到任何地方(或者做任何您想做的事情)。
因此,看完所有組件之后,現(xiàn)在是開始思考如何創(chuàng)建自己的實現(xiàn)的好時機。 在此示例中,我們創(chuàng)建了一個基于Infinispan的持久性方案,并將向您展示實現(xiàn)該方案的所有步驟。
步驟1 :(重新)定義模型
在大多數(shù)情況下,當(dāng)我們想以自己的方式持久流口水時,我們可能會想盡辦法做到。 即使我們不希望更改模型,也可能需要向模型添加特殊注釋才能與您的存儲框架一起使用。 另一個原因可能是您想以一種特殊的方式存儲所有事實,以便與其他舊系統(tǒng)進(jìn)行交叉查詢。 只要您了解所創(chuàng)建的模型,那么每次您在知識會話上調(diào)用方法時,持久性方案都會對它進(jìn)行序列化和反序列化,就可以按照您希望的方式進(jìn)行字面上的重新定義。因此,請始終嘗試使其保持簡單。
這是我們?yōu)檫@種情況創(chuàng)建的模型:
沒什么花哨的,只是流口水相關(guān)的所有事物的扁平化模型。 我們對這種模型不太有想像力,因為我們只是想向您顯示可以更改它。
在該模型中要注意的一件事是,我們?nèi)匀槐4孢@些對象的所有內(nèi)部數(shù)據(jù)的方式與為JPA持久性存儲數(shù)據(jù)的方式幾乎相同。 唯一的區(qū)別是JPA將其存儲在Blob中,而我們將其存儲在Base64加密的字符串中。 如果要更改字節(jié)數(shù)組的生成和讀取方式,則必須創(chuàng)建自己的以下接口實現(xiàn):
- org.kie.api.marshalling.Marshaller進(jìn)行知識講座
- 流程實例的org.jbpm.marshalling.impl.ProcessInstanceMarshaller
但是提供一個示例可能會花費大量時間,甚至可能需要整本書來解釋,因此我們將跳過。
步驟2:實現(xiàn)PersistenceContext
在某些情況下,重新定義PersistenceContext和PersistenceContextManager就足以實現(xiàn)您的所有持久性要求。 PersistenceContext是一個對象,負(fù)責(zé)實現(xiàn)工作項和會話對象的持久化,方法是實現(xiàn)持久化工作項和會話對象的方法,并通過ID查詢它們并將它們從特定的存儲實現(xiàn)中刪除。 PersistenceContextManager負(fù)責(zé)為所有應(yīng)用程序創(chuàng)建一次或在每個命令的基礎(chǔ)上創(chuàng)建PersistenceContext。 comand服務(wù)將在需要時使用它來持久化會話及其對象。
在我們的案例中,我們使用Infinispan緩存作為存儲實現(xiàn)了PersistenceContext和PersistenceContextManager。 不同的PersistenceContextManager實例將可以通過Environment變量訪問所有配置對象。 我們已經(jīng)使用Environment中已定義的鍵來存儲Infinispan相關(guān)的對象:
- EnvironmentName.ENTITY_MANAGER_FACTORY用于存儲基于Infinispan的CacheManager
- EnvironmentName.APP_SCOPED_ENTITY_MANAGER和EnvironmentName.CMD_SCOPED_ENTITY_MANAGER將指向Infinispan緩存對象。
您可以在這里看到該代碼:
在這一點上,我們有一些非常重要的步驟來重新定義我們的流口水持久性。 現(xiàn)在,我們需要知道如何配置我們的知識會議以使用此組件。
步驟3:為我們的工作項目,流程實例和信號創(chuàng)建經(jīng)理
現(xiàn)在我們有了持久性上下文,我們需要教會會議如何正確使用它們。 知識會話具有一些可以配置的管理器,這些管理器使您可以修改或更改默認(rèn)行為。 這些經(jīng)理是:
- org.kie.api.runtime.process.WorkItemManager :它管理工作項目的執(zhí)行時間,將其與適當(dāng)?shù)奶幚沓绦蜻B接,并在工作項目完成時通知流程實例。
- org.jbpm.process.instance.event.SignalManager :它管理何時向進(jìn)程發(fā)送信號或從進(jìn)程發(fā)送信號。 由于流程實例可能被鈍化,因此需要
- org.jbpm.process.instance.ProcessInstanceManager :它管理在創(chuàng)建,啟動,修改或完成流程實例時要采取的動作。
這些接口的JPA實現(xiàn)已經(jīng)可以與持久性上下文管理器一起使用,因此大多數(shù)時候您不需要擴展它們。 但是,與Infinispan相比,我們必須確保流程實例的持久性要比JPA多,因此我們必須以不同的方式實現(xiàn)它們。
一旦有了這些實例,就需要為每種類型的管理器創(chuàng)建一個工廠。接口名稱相同,但后綴“ Factory”除外。 每個用戶都接收一個知識會話作為參數(shù),從中可以獲取環(huán)境對象和所有其他配置。
步驟4:配置知識會話
現(xiàn)在我們已經(jīng)創(chuàng)建了不同的經(jīng)理,我們將需要告訴我們的知識會議以使用它們。 為此,您需要使用SingleSessionCommandService實例創(chuàng)建一個CommandBasedStatefulKnowledgeSession實例。 顧名思義,SingleSessionCommandService是一個用于一次針對一個會話執(zhí)行命令的類。 SingleSessionCommandService的構(gòu)造函數(shù)接收創(chuàng)建適當(dāng)會話并對其執(zhí)行持久化方式所需的所有參數(shù)。 這些參數(shù)是:
- KieBase :具有用于會話運行時的知識定義的知識庫。
- KieSessionConfiguration :我們在其中配置管理器工廠以創(chuàng)建和處理工作項,流程實例和信號。
- 環(huán)境 :用于其他目的的一袋變量,我們將在其中配置持久性上下文管理器對象。
- sessionId(可選) :如果存在,則此參數(shù)在存儲中查找已存在的會話。 否則,它將創(chuàng)建一個新的。
同樣,在我們的示例中,我們使用的是Infinispan,它不是基于引用的存儲,而是基于值的存儲。 這意味著一旦您對infinispan說要存儲一個值,它將存儲它的一個副本而不是實際對象。 流口水持久性中的某些內(nèi)容通過基于引用的存儲進(jìn)行管理,這意味著您可以告訴框架持久化對象,更改其屬性,并在提交事務(wù)后查看存儲在數(shù)據(jù)庫中的那些更改。 使用infinispan不會發(fā)生這種情況,因此您必須在命令執(zhí)行完成后實現(xiàn)對緩存值的更新。 對我們來說幸運的是,SingleSessionCommandService允許我們通過實現(xiàn)攔截器來做到這一點。
攔截器基本上是您自己的命令服務(wù),用于包裝默認(rèn)命令。 您可以告訴每個命令在每次執(zhí)行之前或之后添加更多行為。 這里有一些圖表來解釋它是如何工作的:
如您所見,SingleSessionCommandService允許命令服務(wù)實例實際調(diào)用命令的execute方法。 并且由于命令服務(wù)的攔截器擴展,我們可以在鏈中添加任意數(shù)量的內(nèi)容,從而使我們可以在每次需要執(zhí)行命令時執(zhí)行下一個序列圖之類的內(nèi)容:
在我們的例子中,我們創(chuàng)建了幾個攔截器,并將它們添加到SingleSessionCommandService中。 確保在完成命令后存儲對會話對象所做的所有更改。 另一個允許我們對流程實例對象執(zhí)行相同的操作。
總的來說,這是我們現(xiàn)在需要創(chuàng)建知識會話以實際使用infinispan作為持久性方案的方式:
復(fù)雜吧? 不用擔(dān)心 還有另外兩類可以簡化配置。
步驟4:創(chuàng)建我們自己的啟動服務(wù)
是的,每次我們想要創(chuàng)建自己的自定義持久性知識會話時,我們都可以編寫大量代碼。 這是一個自由的世界(大部分情況下)。 但是,您也可以將此實現(xiàn)包裝在帶有兩個公開方法的單個類中:
- 一個創(chuàng)建新的會話
- 一個加載先前存在的會話
并在內(nèi)部創(chuàng)建所有配置,并在需要更改一項或多項更改時將其合并。 Drools提供了一個接口來充當(dāng)此協(xié)議的接口,稱為org.kie.api.persistence.jpa.KieStoreServices
我們創(chuàng)建了此接口的自己實現(xiàn),并且還創(chuàng)建了一個靜態(tài)類(稱為InfinispanKnowledgeService)來訪問該接口。 這使我們能夠創(chuàng)建如下會話:
結(jié)論
流口水的持久性似乎很難理解和工作,更不用說以自己的方式實現(xiàn)它了。 但是,我希望這對那些需要以特殊方式實現(xiàn)流口水持久性,或者甚至想知道是否可以通過JPA以外的其他方式實現(xiàn)流口水持久性的人有點神秘。
另外,如果您希望看到為使其工作而進(jìn)行的修改,請參見以下三個請求請求:
- https://github.com/droolsjbpm/droolsjbpm-build-bootstrap/pull/38
- https://github.com/droolsjbpm/drools/pull/198
- https://github.com/droolsjbpm/jbpm/pull/166
在此JIRA票證中指定了向Drools添加此功能的功能請求。 如果您希望將其作為核心drools項目的一部分,可以隨時對其進(jìn)行投票!
翻譯自: https://www.javacodegeeks.com/2013/05/creating-your-own-drools-and-jbpm-persistence-with-infinispan.html
總結(jié)
以上是生活随笔為你收集整理的使用Infinispan创建自己的Drools和jBPM持久性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux编程(在linux下编程)
- 下一篇: 战车大战最新版(战车大战安卓)