在您好的應用程序中使用一個新的流程
流程處理
(1)你需要建立一個知識庫,其中包含過程定義
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); |
kbuilder.add( ResourceFactory.newClassPathResource( "MyProcess.bpmn2" ), |
加入你的進程生成器(可以添加多個進程)後,您可以創建一個新的知識基礎,這樣的:
KnowledgeBase kbase = kbuilder.newKnowledgeBase(); |
請注意,這將拋出一個異常,如果知識庫包含錯誤(因爲它不能正確地分析您的流程)。
(2)你需要創建一個會話,溝通與流程引擎和啓動過程的啓動過程。
啓動過程:啓動一個特定的進程,你會需要調用您的會話的startProcess方法,並傳遞您要啓動的進程的ID。例如:
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); |
ksession.startProcess( "com.sample.hello" ); |
startProcess方法的參數是需要啓動的進程ID。當定義一個過程,這需要作爲一個過程的財產(例如在Eclipse的屬性視圖顯示,當您單擊過程中的背景畫布)指定進程ID。
當您啓動的過程中,你可以指定額外的參數,用來傳遞額外的輸入數據的過程中,使用startProcess(絃樂進程ID,地圖參數)方法。額外的參數是一個名稱
- 值對的集合。這些參數將被複制到新創建的進程實例的頂層變量的過程,所以他們可以在你的進程餘下的直接訪問。
數據
雖然流程圖上指定的過程控制流的重點,它通常也有必要的過程,從數據的角度看。在整個執行過程中,數據可以檢索,存儲,傳遞和使用。
對於運行時的數據,存儲在執行過程中中,過程變量都可以使用。變量是一個名稱和一個數據類型定義。這可能是一個基本數據類型,如布爾,INT,或String,或任何Object的子類。變量可以定義一個變量的範圍內。頂層的範圍是過程本身的變量的範圍。Subscopes可以定義使用一個子進程。子範圍定義的變量只在該範圍內的節點訪問。
每當訪問一個變量,這個進程將尋找合適的變量範圍定義變量。變量作用域的嵌套是不允許的。節點總是會尋找其父容器中的一個變量。如果無法找到該變量,它會看,一個人的父容器,等等,直到達到流程實例本身。如果無法找到該變量,讀訪問產量空,寫訪問會產生錯誤消息,繼續執行的過程。
變量可以用各種方式:
- 流程級別的變量,可以設置啓動時所提供的參數映射到thestartProcess方法調用一個過程。這些參數將作爲進程範圍的變量。
- 腳本操作,只需直接使用在其腳本的本地參數變量的名稱可以訪問的變量。例如,如果程序定義了一個變量類型“org.jbpm.Person”的過程中,在這個過程中的腳本可以訪問此直接:person.setAge(10);更改一個腳本中的變量的值可以通過知識背景下:kcontext.setVariable(variableName,
value);
- 服務任務(可重複使用的子過程)可以通過向外界(或另一個進程實例)過程變量的值變量映射到一個傳出參數。例如,服務任務的參數映射可以定義的過程變量x的值應被映射到一個任務參數y對前被調用服務。您還可以注入一個硬編碼的參數字符串,使用#{表達式}的過程變量值。例如,可以定義一個人的任務的描述,您需要聯絡人#{person.getName()}(其中人是一個過程變量),這個表達式將取代人的實際名稱服務時需要調用。同樣的服務(或可重複使用的子進程)的結果也可以被複製使用結果映射到一個變量。
- 各種其他節點也可以訪問數據。例如事件節點可以存儲在變量中的事件關聯的數據,等檢查的更多信息,不同的節點類型的屬性。
最後,流程和規則都進入到全局,即全局變量和知識會話中的數據。的全局在行動就像變量直接訪問。全局需要定義作爲這一進程的一部分,纔可以使用。例如,按一下指定動作腳本在Eclipse行動的屬性編輯器時,全局按鈕您可以定義的全局。您還可以設置一個全球從外面使用ksession.setGlobal(名稱,值),或從內部使用kcontext.getKnowledgeRuntime()的過程腳本的價值在setglobal(名稱,值);
約束
約束可用於在不同的地點,在你的流程,例如在一個不同的網關。jBPM支持兩種類型的約束:
- 守則約束的布爾表達式,他們到達時直接評價。我們目前支持兩種方言表達這些代碼限制:Java和MVEL。Java和MVEL代碼的限制直接訪問,並在這個過程中中定義的全局變量。下面是一個有效的Java代碼的約束,人在這個過程中的一個變量的一個例子:return
person.getAge()>20;一個類似的例子是一個有效MVEL代碼約束:return
person.age > 20;
- 規則約束等於正常的Drools的規則條件。他們使用了Drools規則語言語法表達可能是複雜的約束。這些規則可以像任何其他規則,是指在工作內存中的數據。他們還可以直接向全局。下面是一個有效的規則約束的例子:Person(
age > 20 )
規則約束,沒有直接訪問內部的過程中定義的變量。不過,這是有可能加入流程實例工作記憶在你的規則約束和匹配過程實例內的規則約束,指當前進程的實例。我們已經添加了特殊的邏輯,以確保變量的類型WorkflowProcessInstance流程實例將只匹配當前進程的實例,而不是在工作內存中的其他進程實例。請注意,不過,你是負責自己插入到會話的過程實例,可能的話,更新它,例如,使用Java代碼或在你的進程進入或退出或明確的行動。規則的約束下面的例子將一個人在變量“名稱”的過程中存儲的值相同的名稱搜索:
processInstance : WorkflowProcessInstance() |
Person( name == ( processInstance.getVariable( "name" ) ) ) |
# add more constraints here ... |
動作角本
動作腳本可以使用不同的方式:
操作全局和過程和預定義變量kcontext的定義的變量的訪問。此變量的類型org.drools.runtime.process.ProcessContext,可用於多個任務:
獲取當前節點的實例(如適用)。節點的實例,如它的名稱和類型的數據,可以查詢。您還可以取消當前節點的實例。
NodeInstance node = kcontext.getNodeInstance(); |
String name = node.getNodeName(); |
獲取當前進程的實例。可以查詢流程實例數據(名稱,ID,進程ID等),中止或暗示內部事件。
ProcessInstance proc = kcontext.getProcessInstance(); |
proc.signalEvent( type, eventObject ); |
獲取或設置變量的值。
訪問知識庫中運行時,允許你不喜歡的東西開始一個進程,信號(外部)事件,插入數據,等
jBPM的目前支持兩種方言,Java和MVEL。Java的行動應該是有效的Java代碼。MVEL行動可以使用的業務腳本語言MVEL表達的行動。MVEL接受任何有效的Java代碼,但此外提供支持嵌套的參數訪問(例如,person.name,而不是person.getName()),和許多其他的腳本改進。因此,MVEL表達式爲商業用戶更方便。例如,一個動作,打印出的人在“請求者”的過程變量的名稱看起來像這樣:
System. out .println( person.getName() ); |
System. out .println( person.name ); |
活動
在執行過程中,流程引擎可以確保所有相關的任務是根據工藝方案執行,請求執行的工作項目,並等待結果。然而,它也有可能這一進程應作出迴應,不直接由流程引擎要求的事件。明確代表這些事件的過程中允許指定過程中應如何應對此類事件的過程作者。
事件有一個類型,可能與他們相關的數據。用戶可以自由定義自己的事件類型及其相關的數據。
一個進程可以指定如何使用消息事件響應的事件。一個事件節點需要指定類型的事件節點感興趣,它也可以定義一個變量的名字,這將收到與該事件相關的數據。這使得在這個過程中的後續節點訪問事件數據,並根據該數據,採取適當的行動。
事件可能標誌着一個在多種方式的過程正在運行的實例:
內部事件:任何一個進程內的行動(例如,行動節點的行動,或一些節點上進入或退出行動)信號的內部事件的發生,周圍的流程實例,使用類似的代碼以下內容:
kcontext.getProcessInstance().signalEvent(type, eventData); |
外部事件:事件通知一個流程實例可以從外面用,如代碼:
processInstance.signalEvent(type, eventData); |
使用事件相關,而是直接通知一個流程實例的外部事件,它也可以讓發動機自動確定流程實例可能會使用事件的相關性,這是基於事件類型的事件感興趣。這樣的事件發生時,一個流程實例包含事件節點聽某種類型的外部事件通知。信號此類事件的流程引擎,寫代碼,如:
ksession.signalEvent(type, eventData); |
事件也可以被用來啓動一個進程。每當消息開始事件定義一個特定類型的事件觸發,將會啓動新的流程實例,每次事件的類型,信號流程引擎。
計時器
計時器等待一個預定義的時間,觸發前,一次或多次。他們可以使用一段時間後觸發一定的邏輯關係,或定期重複某些動作。
定時器節點設置一個延遲和一個時期。延遲指定的時間節點激活後等待觸發定時器首次。這一時期定義隨後觸發激活之間的時間。期間,一個在單次觸發定時器0的結果。
表達的形式應[#][#H] [#M] [#S] [#[MS]。這意味着,您可以指定天,小時,分鐘,秒和multiseconds(這是默認的,如果你不指定任何)的數量。例如,表達“1H”將等待觸發定時器(再次)一小時。
負責確保在適當的時候觸發,定時器得到的定時服務。定時器也被取消,這意味着將不再被觸發定時器。
定時器可用於在一個進程內的兩個方面:
計時器事件可能會增加流動過程。其激活啓動定時器,它觸發時,一次或多次,它會激活定時器節點的繼任者。這意味着,以積極的時期傳出連接定時器觸發多次。取消定時器節點也取消了相關的計時器,在這之後沒有更多的觸發會發生。
定時器可以與一個子進程,作爲一個邊界事件。但是,這是目前唯一可能直接在XML。我們將加入支持在新的BPMN2編輯器以圖形方式指定。
更新流程
隨着時間的推移,流程可能演變例如,因爲這個過程本身需要加以改進,或由於不斷變化的需求。其實,你真的不能更新的過程,你只能部署一個新版本的過程中,舊的過程將依然存在。這是因爲現有的流程實例,可能還需要這一過程定義。因此,新的過程,應該有一個不同的ID,雖然名稱可能是相同的,可以使用的版本參數表明,當一個進程更新(版本參數只是一個字符串,而不是進程的框架本身的驗證,所以你可以選擇自己的格式,用於指定小/大的更新等)。
每當一個更新過程,重要的是,以確定哪些應該發生到已經運行的進程實例。有不同的策略之一,可以考慮爲每個運行實例:
步驟操作:正在運行的進程實例的收益爲正常,因爲它是定義流程實例啓動時,下面的過程(定義)。因此,已經運行的實例會進行過程中,彷彿從來沒有更新。新的實例可以開始使用更新的過程。
中止並重新啓動已經運行的實例被中止。如果有必要,可以重新啓動的過程實例,使用新的流程定義。
傳輸:過程實例遷移到新的流程定義,含義, -一旦它被成功遷移 -
將繼續執行的基礎上更新的過程邏輯。
默認情況下,jBPM的使用進行的方法,這意味着可以部署同一進程的多個版本,但現有的流程實例將簡單的啓動流程實例時所使用的流程定義的基礎上繼續執行。總是可以被中止正在運行的進程實例,以及當然,在使用過程中的管理API。過程實例遷移是比較困難的,是在下面的段落解釋。
流程實例的遷移
一個流程實例包含所有運行中的信息,需要繼續執行一些在稍後的時間點。這包括所有鏈接到這個過程實例(如變量)的數據,而且在這個過程中圖的當前狀態。對於當前處於活動狀態的每個節點,一個節點的實例是用來表示。這個節點的實例,也可以包含額外的狀態鏈接到僅該特定節點的執行。有不同類型的節點實例,每個類型的節點之一。
一個流程實例只包含運行時的狀態,並鏈接到一個特定的進程(間接使用ID引用)表示在執行這個流程實例(這明確的定義和運行時狀態分離時,需要遵循的流程邏輯允許重用的跨越這個過程中,最大限度地減少運行時的狀態爲基礎的所有流程實例)的定義。因此,更新一個正在運行的進程實例,所以它使用了新的進程邏輯,而不是舊到新的版本是一個簡單的改變從舊到新的ID引用的進程ID的問題。
但是,這並沒有考慮到流程實例的狀態(變量實例和節點實例)以及可能需要遷移。僅擴展的過程和所有現有的等待狀態保持的情況下,這是非常簡單,流程實例的運行狀態並不需要改變。然而,也有可能是一個更sofisticated的映射是必要的。例如,現有的等待狀態時被刪除,或分割成多個等待狀態,等待在該國現有流程實例,不能簡單地更新。或者引入一個新的進程變量時,該變量可能需要initiazed正確的,因此它可以在(更新)過程中的其餘部分使用。
WorkflowProcessInstanceUpgrader可以使用工作流過程實例升級到一個新的流程實例。當然,您需要提供的流程實例和新的進程ID。默認情況下,jBPM將自動新節點具有相同的ID實例映射舊節點實例。但是你可以提供一個舊的(唯一的)節點ID映射到新的節點ID。惟一的節點ID的節點ID,其父母的節點ID(冒號inbetween)之前,允許唯一標識一個節點時使用複合節點(節點ID節點容器內只有獨特。新的節點ID簡直是在新的節點ID節點的容器(所以這裏沒有惟一的節點ID,只是新的節點ID)。下面的代碼片段顯示了一個簡單的例子。
KnowledgeBuilder kbuilder = ... |
StatefulKnowledgeSession ksession = ... |
ProcessInstance processInstance = ksession.startProcess( "com.sample.process" ); |
kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); |
kbuilder.add(..., ResourceType.BPMN2); |
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages()); |
Map<String, Long> mapping = new HashMap<String, Long>(); |
WorkflowProcessInstanceUpgrader.upgradeProcessInstance( |
ksession, processInstance.getId(), |
"com.sample.process2" , mapping); |
如果這種映射仍然不足,你仍然可以描述自己的自定義映射器,針對具體情況。請務必先斷開流程實例,相應地改變狀態,然後重新連接的過程實例,類似如何WorkflowProcessinstanceUpgrader它。
業務流程模型和符號(BPMN)2.0規範
BPMN的主要目標是提供一個符號,是所有業務用戶容易理解的, |
業務流程模型和符號(BPMN)2.0規範,不僅定義了一個標準,就如何以圖形方式表示業務流程(如BPMN1.x的)是OMG規範,但現在還包括爲執行定義的元素語義,和XML格式(股)如何存儲過程定義。
jBPM5允許執行使用的BPMN 2.0的XML格式定義的流程。這意味着,您可以使用所有不同的jBPM5模具模型,執行,管理和監控您的業務流程,指定可執行的業務流程中使用的BPMN2.0格式。事實上,完整的BPMN
2.0規範還包括如何表示像編排和和協作的事情的細節。然而,jBPM項目的重點部分,可用於指定可執行流程的規範。
BPMN中的可執行文件的進程,包括不同類型的節點被連接到對方使用順序流。BPMN
2.0規範定義了三種主要類型的節點:
事件:它們用於模型中的特定事件的發生。這可能是一個開始事件(即用來指示的過程中開始),結束事件(定義過程結束,或該子流)和中間事件(指示的執行過程中可能出現的事件過程)。
活動:這些定義,需要在執行過程中執行不同的動作。存在不同類型的任務,對活動的類型取決於您嘗試模型(如人工的任務,服務任務等)和actvities也可以嵌套(使用不同類型的子進程)。
網關:可以被用來定義多個路徑的過程中。根據網關類型,這些可能表明並行執行,選擇等
jBPM5沒有實現在BPMN 2.0規範定義的所有元素和屬性。然而,我們支持一個顯著的子集,包括可執行的流程內,可使用的最常見的節點類型。這包括幾乎所有元素,並在BPMN
2.0規範的“共同的可執行文件”子類與一些額外的元素和屬性,我們相信擴展,定義的屬性,以及在這方面的寶貴。下面可以找到全套支持的元素和屬性,但它包含了像元素:
流程對象包括
- Flow objects
- Events
- Start Event (None, Conditional, Signal, Message, Timer)
- End Event (None, Terminate, Error, Escalation, Signal, Message, Compensation)
- Intermediate Catch Event (Signal, Timer, Conditional, Message)
- Intermediate Throw Event (None, Signal, Escalation, Message, Compensation)
- Non-interrupting Boundary Event (Escalation, Timer)
- Interrupting Boundary Event (Escalation, Error, Timer, Compensation)
- Activities
- Script Task
- Task
- Service Task
- User Task
- Business Rule Task
- Manual Task
- Send Task
- Receive Task
- Reusable Sub-Process (Call Activity)
- Embedded Sub-Process
- Ad-Hoc Sub-Process
- Data-Object
- Gateways
- Diverging
- Exclusive
- Inclusive
- Parallel
- Event-Based
- Converging
- Lanes
- Data
- Java type language
- Process properties
- Embedded Sub-Process properties
- Activity properties
- Connecting objects
例如,考慮下面的“你好世界”BPMN 2.0的過程中,它什麼也不做,寫一個“Hello World”的說法時,過程開始。
這個過程的可執行版本使用BPMN 2.0的XML表示會看起來像這樣:
<?xml version= "1.0" encoding= "UTF-8" ?> |
<definitions id= "Definition" |
<process processType= "Private" isExecutable= "true"
id= "com.sample.HelloWorld"
name= "Hello World"
> |
<startEvent id= "_1" name= "StartProcess"
/> |
<scriptTask id= "_2" name= "Hello"
> |
<script>System. out .println( "Hello World" );</script> |
<endEvent id= "_3" name= "EndProcess"
> |
<terminateEventDefinition/> |
<sequenceFlow id= "_1-_2" sourceRef= "_1"
targetRef= "_2"
/> |
<sequenceFlow id= "_2-_3" sourceRef= "_2"
targetRef= "_3"
/> |
<bpmndi:BPMNPlane bpmnElement= "Minimal" > |
<bpmndi:BPMNShape bpmnElement= "_1" > |
<dc:Bounds x= "15" y= "91"
width= "48"
height= "48" /> |
<bpmndi:BPMNShape bpmnElement= "_2" > |
<dc:Bounds x= "95" y= "88"
width= "83"
height= "48" /> |
<bpmndi:BPMNShape bpmnElement= "_3" > |
<dc:Bounds x= "258" y= "86"
width= "48"
height= "48" /> |
<bpmndi:BPMNEdge bpmnElement= "_1-_2" > |
<di:waypoint x= "39" y= "115"
/> |
<di:waypoint x= "75" y= "46"
/> |
<di:waypoint x= "136" y= "112"
/> |
<bpmndi:BPMNEdge bpmnElement= "_2-_3" > |
<di:waypoint x= "136" y= "112"
/> |
<di:waypoint x= "240" y= "240"
/> |
<di:waypoint x= "282" y= "110"
/> |
要創建自己的過程,使用BPMN 2.0的格式,你可以
創建一個新的流文件,使用DroolsEclipse插件的嚮導,在嚮導的最後一頁,確保你選擇的Drools5.1的代碼兼容性。使用BPMN
2.0的XML格式,這將創建一個新的進程。但是請注意,這是不完全的BPMN 2.0編輯器,因爲它仍然使用不同屬性的名稱等,但它確實保存過程中使用有效的BPMN2.0的語法。另外請注意,編輯器不支持所有節點類型和已在執行引擎支持的屬性。
設計師是一個開源的基於Web的編輯器,支持BPMN2.0格式。我們已經嵌入到GuvnorBPMN 2.0的流程可視化和編輯。你可以使用Designer(獨立或集成)創建/編輯BPMN
2.0流程,然後出口到BPMN 2.0的格式,或將其保存到Guvnor,使他們能夠執行。
正在創建一個新的BPMN2的Eclipse插件,支持完整的BPMN2規範。這是目前仍在開發中,只支持數量有限的結構和屬性,但已經可以用來創建簡單的BPMN2流程。要創建一個新的BPMN2的這個編輯器的文件,使用嚮導(下例子)創建一個新的BPMN2的文件,這將產生一個。BPMN2文件和一個。珠三角文件包含圖形信息。雙擊。珠三角文件中使用的圖形化編輯器編輯該文件。
通過直接寫入XML,您可以隨時手動創建BPMN 2.0的流程文件。您可以對BPMN 2.0的XSD驗證你的流程的語法,或在Eclipse插件的使用驗證器來檢查你的模型的語法和完整性。
下面的代碼片段顯示了你如何加載到你的知識庫一個BPMN2的過程......
private static KnowledgeBase createKnowledgeBase() throws Exception { |
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); |
kbuilder.add(ResourceFactory.newClassPathResource( "sample.bpmn2" ), ResourceType.BPMN2); |
return kbuilder.newKnowledgeBase(); |
... ...如何執行此過程中......
KnowledgeBase kbase = createKnowledgeBase(); |
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); |
ksession.startProcess( "com.sample.HelloWorld" ); |
持久化和轉換
jBPM的持久存儲允許某些信息,即流程的運行時的狀態,歷史信息等
1)運行時狀態
每當啓動一個過程,一個過程實例被創建,它代表的過程,在這種特定情況下執行。例如,在執行的過程中,指定如何處理銷售訂單時,一個流程實例創建要求每個銷售。流程實例代表當前的執行狀態,在這種特定情況下,並包含所有相關信息,流程實例。請注意,它僅包含最小的運行狀態,需要繼續這一進程的實例在執行一段時間後,但它不包括對這一進程的實例歷史的信息,如果該信息不再需要在流程實例。
執行過程中的運行狀態,可以持久的,例如,在數據庫中。這使得恢復意外故障的情況下,所有正在運行的進程的執行狀態,或者暫時從內存中刪除正在運行的實例,並在一段時間後恢復它們。jBPM的允許您插入不同的持久性策略。默認情況下,如果你不配置的流程引擎,否則,流程實例沒有持久性。
二進制持久性
jBPM提供了一個二進制的持久性機制,允許您保存爲二進制數據集的一個流程實例的狀態。通過這種方式,所有正在運行的進程實例的狀態總是可以被儲存在一個持久的位置。請注意,這些二進制數據集通常都比較小,因爲它們只包含最小的流程實例的執行狀態。對於一個簡單的過程實例,這通常包含一個或幾個節點的實例,即任何節點當前正在執行,並且,可能的話,一些變量的值。
安全點
一個流程實例的狀態存儲在流程引擎執行所謂的“安全點”。每當一個流程實例執行後啓動或從一個等待狀態的延續,發引擎的收益可以執行,直到沒有更多的行動。在這一點上,引擎已達到未來的安全狀態,並堅持存儲過程實例的狀態和所有其他的進程有可能受到影響的實例。
配置持久性
默認情況下,流程引擎不保存運行時的數據持續。然而,它可以通過非常簡單的配置做到這一點,通過添加一個配置文件和必要的依賴。基於Java持久性API(JPA)的持久性本身,因此可以與幾個持久性機制。我們使用Hibernate在默認有情況下。用H2數據庫來存儲數據,但你可以選擇你自己的選擇。
首先,你需要添加必要的依存關係到你的classpath。如果你使用Eclipse IDE,你可以通過添加JAR文件到你的jBPM運行時目錄,或通過手動添加這些依賴關係到您的項目。首先,你需要的JAR文件與jBPM持久化jpa.jar,包含用於保存運行時的狀態,必要時的代碼。接下來,您還需要其他各種依賴關係,具體取決於您使用的持久性解決方案和數據庫。與Hibernate作爲JPA持久性提供程序,H2數據庫和JTA的事務管理Bitronix默認組合,下面的列表是需要額外的依賴:
- jbpm-persistence-jpa (org.jbpm)
- drools-persistence-jpa (org.drools)
- persistence-api (javax.persistence)
- hibernate-entitymanager (org.hibernate)
- hibernate-annotations (org.hibernate)
- hibernate-commons-annotations (org.hibernate)
- hibernate-core (org.hibernate)
- dom4j (dom4j)
- jta (javax.transaction)
- btm (org.codehaus.btm)
- javassist (javassist)
- slf4j-api (org.slf4j)
- slf4j-jdk14 (org.slf4j)
- h2 (com.h2database)
- commons-collections (commons-collections)
接下來,您需要配置jBPM引擎在必要時保存引擎的狀態。要做到這一點最簡單的方法是使用JPAKnowledgeService創建您的知識會話,基於知識基礎,知識的會話配置(如有必要)和環境。環境需要包含您的實體管理器工廠的引用。例如:
EntityManagerFactory emf = |
Persistence.createEntityManagerFactory( "org.jbpm.persistence.jpa"
); |
Environment env = KnowledgeBaseFactory.newEnvironment(); |
env. set ( EnvironmentName.ENTITY_MANAGER_FACTORY, emf ); |
StatefulKnowledgeSession ksession = |
JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null , env ); |
int sessionId = ksession.getId(); |
ksession.startProcess( "MyProcess" ); |
您還可以YSE的JPAKnowledgeService重新創建基於一個特定的會話ID的會話:
ksession = JPAKnowledgeService.loadStatefulKnowledgeSession( sessionId, kbase, null , env ); |
請注意,我們只保存最小的狀態,是需要繼續在以後的某個點的執行過程實例。這意味着,例如,它不包含已經執行的節點的信息,如果該信息不再是相關的,或已完成或中止從數據庫中刪除該進程的實例。如果你想搜索歷史相關的信息,你應該使用的歷史記錄,後面會解釋。
你需要添加一個持久性配置到你的classpath配置JPA的使用Hibernate和H2數據庫(或您的偏好),名爲persistence.xml的META
- INF目錄中,如下所示。對於如何改變自己的配置的更多細節,我們指的JPA和Hibernate文檔瞭解更多信息。
<?xml version= "1.0" encoding= "UTF-8"
standalone= "yes" ?> |
<persistence-unit name= "org.jbpm.persistence.jpa" > |
<provider>org.hibernate.ejb.HibernatePersistence</provider> |
<jta-data-source>jdbc/processInstanceDS</jta-data-source> |
< class >org.drools.persistence.info.SessionInfo</ class > |
< class >org.jbpm.persistence.processinstance.ProcessInstanceInfo</ class > |
< class >org.drools.persistence.info.WorkItemInfo</ class > |
<property name= "hibernate.dialect" value= "org.hibernate.dialect.H2Dialect" /> |
<property name= "hibernate.max_fetch_depth" value= "3" /> |
<property name= "hibernate.hbm2ddl.auto" value= "update" /> |
<property name= "hibernate.show_sql" value= "true" /> |
<property name= "hibernate.transaction.manager_lookup_class" |
value= "org.hibernate.transaction.BTMTransactionManagerLookup" /> |
這個配置文件是指所謂的“JDBC /processInstanceDS”數據源。下面的Java代碼片段可以用來設置該數據源,在這裏我們使用的是基於文件的H2數據庫。
PoolingDataSource ds = new PoolingDataSource(); |
ds.setUniqueName( "jdbc/testDS1" ); |
ds.setClassName( "org.h2.jdbcx.JdbcDataSource" ); |
ds.setAllowLocalTransactions( true ); |
ds.getDriverProperties().put( "user" , "sa" ); |
ds.getDriverProperties().put( "password" , "sasa" ); |
ds.getDriverProperties().put( "URL" , "jdbc:h2:file:/NotBackedUp/data/process-instance-db" ); |
如果你部署到應用服務器,通常可以deploy目錄中的配置文件,例如,創建一個數據源:
<?xml version= "1.0" encoding= "UTF-8" ?> |
<jndi-name>jdbc/testDS1</jndi-name> |
<connection-url>jdbc:h2:file:/NotBackedUp/data/process-instance-db</connection-url> |
<driver- class >org.h2.jdbcx.JdbcDataSource</driver- class > |
<user-name>sa</user-name> |
<password>sasa</password> |
2)轉換
只要你不提供您的應用程序內的事務邊界,發動機對發動機會自動執行一個單獨的事務中的每個方法調用。如果這種行爲是可以接受的的,你不需要做別的。你可以,但是,也可以指定自己的事務邊界。例如,這可以讓你組合成一個事務的多個命令。
您需要註冊後在環境中使用用戶定義的事務之前,事務管理器。下面的代碼示例使用的Bitronix事務管理。接下來,我們使用Java事務API(JTA),指定事務邊界,如下圖所示:
EntityManagerFactory emf = |
Persistence.createEntityManagerFactory( "org.jbpm.persistence.jpa"
); |
Environment env = KnowledgeBaseFactory.newEnvironment(); |
env. set ( EnvironmentName.ENTITY_MANAGER_FACTORY, emf ); |
env. set ( EnvironmentName.TRANSACTION_MANAGER, |
TransactionManagerServices.getTransactionManager() ); |
StatefulKnowledgeSession ksession = |
JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null , env ); |
(UserTransaction) new
InitialContext().lookup( "java:comp/UserTransaction"
); |
ksession.insert( new Person(
"John Doe" ) ); |
ksession.startProcess( "MyProcess" ); |
流程定義
流程定義文件通常被寫在一個XML格式。這些文件可以很容易地存儲在文件系統在開發過程中。但是,只要你想使你的知識在生產中的一個或多個引擎訪問,我們建議使用(邏輯)你的知識集中在一個或多個知識庫Guvnor是Drools的一個分項目,提供這一點。它由一個倉庫,用於存儲不同類型的知識,不僅流程定義,但也規則,對象模型等,它允許使用WebDAV的知識或運用知識代理,當創建一個自動下載信息Guvnor便於檢索的知識基礎,提供了一個Web應用程序,允許業務用戶可以查看和更新知識信息庫中的信息。如何做到這一點的更多信息,檢索的DroolsGuvnor文檔。
歷史記錄
在許多情況下是非常有用(如果沒有必要的話)的存儲流程實例的執行信息,使這一信息可用於事後,例如,爲了驗證一個特定的流程實例執行過什麼行動,或監測和分析一個特定的進程效率。在運行時數據庫中存儲的歷史信息通常不是一個好主意,因爲這將導致在不斷增長的運行數據,監測和分析,查詢可能會影響您的運行時引擎的性能。這就是爲什麼歷史的流程實例的執行信息是分開存儲。
這執行信息的歷史記錄是創建基於流程引擎在執行過程中生成的事件。jBPM運行時引擎提供了一個通用的機制,聽取各種不同的事件。必要的信息可以很容易地從這些事件中提取中,持久化,例如在數據庫中,。過濾器可用於存儲你找到相關的信息。
存儲在數據庫中處理事件
jBPM的BAM模塊包含一個事件監聽器進程相關的信息存儲在一個數據庫,直接使用JPA或Hibernate。該數據庫包含了兩個表,一個流程實例信息和一個節點實例的信息(見下圖):
1.ProcessInstanceLog:這列出的過程實例ID,進程(定義)ID,開始日期和(如適用)的所有流程實例的結束日期。
2.NodeInstanceLog:此表包含哪些節點實際上每個流程實例內執行的更詳細的信息。每當一個節點實例進入進來的連接,或通過其傳出連接退出,這些信息是存儲在此表中中。對於這一點,它存儲過程實例ID和它正在執行中的流程實例的進程ID和節點實例ID和相應的節點ID的節點實例中的問題(在這個過程中定義)。最後,事件的類型(0=輸入,1
=退出)和事件的日期,以及存儲。
日誌數據庫在這樣的歷史進程信息,您需要註冊您的會話(或工作記憶)的記錄,像這樣的:
StatefulKnowledgeSession ksession = ...; |
JPAWorkingMemoryDbLogger logger =
new JPAWorkingMemoryDbLogger(ksession); |
請注意,此記錄是像其他任何審計記錄器,這意味着你可以調用的方法addFilter,以確保只有相關信息存儲在數據庫中添加一個或多個過濾器。只有所有過濾器所接受的的信息會出現在數據庫中。它不再需要時,您應將該記錄器。
要指定應存儲信息的數據庫,修改的文件persistence.xml文件,包括審計日誌類以及(ProcessInstanceLog,NodeInstanceLog和VariableInstanceLog),如下所示。
<?xml version= "1.0" encoding= "UTF-8"
standalone= "yes" ?> |
<persistence-unit name= "org.jbpm.persistence.jpa" > |
<provider>org.hibernate.ejb.HibernatePersistence</provider> |
<jta-data-source>jdbc/processInstanceDS</jta-data-source> |
< class >org.drools.persistence.info.SessionInfo</ class > |
< class >org.jbpm.persistence.processinstance.ProcessInstanceInfo</ class > |
< class >org.drools.persistence.info.WorkItemInfo</ class > |
< class >org.jbpm.process.audit.ProcessInstanceLog</ class > |
< class >org.jbpm.process.audit.NodeInstanceLog</ class > |
< class >org.jbpm.process.audit.VariableInstanceLog</ class > |
<property name= "hibernate.dialect" value= "org.hibernate.dialect.H2Dialect" /> |
<property name= "hibernate.max_fetch_depth" value= "3" /> |
<property name= "hibernate.hbm2ddl.auto" value= "update" /> |
<property name= "hibernate.show_sql" value= "true" /> |
<property name= "hibernate.transaction.manager_lookup_class" |
value= "org.hibernate.transaction.BTMTransactionManagerLookup" /> |
所有這些信息可以方便地查詢和使用,在很多不同的使用情況,從創建一個特定的流程實例分析特定進程的所有實例的性能的歷史記錄。
只應考慮該審計日誌的默認實現。我們不知道你需要什麼樣的信息存儲進行分析之後,由於性能原因,建議只存儲有關數據。根據你的用例,你可能會定義您自己的數據模型,用於存儲你需要的信息,並在使用過程中的事件監聽器來提取這些信息。