歡迎您光臨本站 註冊首頁

jBPM-4.0中文開發指南-第13章 執行模式

←手機掃碼閱讀     火星人 @ 2014-03-10 , reply:0

第 13 章 執行模式

這裡有三種基本的流程執行模式:對象,持久化和嵌入. 對於持久化和嵌入執行模式, 流程執行必須在一個事務中執行.在那種情況, 流程執行必須放在一個環境的內部. 環境將用來綁定流程執行,更新到一個應用事務的事務中. 環境可以被用來綁定,比如一個JDBC連接, JTA,BMT,Spring事務等等.

13.1. 對象執行模式

對象執行模式是使用流程虛擬機的最簡單形式. 這意味著通過客戶端API直接使用流程定義和執行對象. 讓我們通過一個例子演示這個. 我們通過創建一個ClientProcessDefinition開始,看起來像這樣:

對象執行模式是使用流程虛擬機的最簡單形式. 這意味著通過客戶端API直接使用流程定義和執行對象. 讓我們通過一個例子演示這個. 我們通過創建一個ClientProcessDefinition開始,看起來像這樣:

圖 13.1. 貸款流程

ClientProcessDefinition processDefinition = ProcessFactory.build("loan")
.activity("submit loan request").initial().behaviour(AutomaticActivity.class)
.transition().to("evaluate")
.activity("evaluate").behaviour(WaitState.class)
.transition("approve").to("wire money")
.transition("reject").to("end")
.activity("wire money").behaviour(AutomaticActivity.class)
.transition().to("archive")
.activity("archive").behaviour(WaitState.class)
.transition().to("end")
.activity("end").behaviour(WaitState.class)
.done();

ProcessFactory是一個幫助類, 為構建一個表現為流程定義的對象圖提供方便. AutomaticActivity是一個通過活動, 沒有任何操作發生,WaitState會等到外部signal發生. 這兩個活動實現都會在後面討論更深.

processDefinition對象作為一個工廠,為流程實例對象. 一個流程實例表現為流程定義的一個執行. 更準確的說,流程實例是執行的主路徑.

ClientExecution execution = processDefinition.startProcessInstance();

一個流程實例自己也是一個Execution. 潛在的,一個執行可以擁有子執行 表現執行的同步路徑.

execution可以看做是一個狀態機, 在流程定義里像描述一樣操作.啟動一個流程實例意思是 流程定義的初始節點被執行. 這是一個自動活動,執行會執行到evaluate活動. evaluate活動是一個等待狀態. 當執行到達evaluate活動,startProcessInstance方法 會返回並等待一個外部signal使用signal方法提供. 在startProcessInstance之後,我們可以證實 如果執行定位在evaluate活動.

assertEquals("evaluate", execution.getActivityName());

為了讓流程執行得更遠,我們提供一個外部觸發器使用 signal方法.執行的結果會被作為 signalName參數給與,像這樣:

execution.signal("approve");

WaitState活動實現會根據給出的signalName 選擇轉移.執行將執行自動活動wire money 然後在進入等待狀態archive后 返回.

assertEquals("archive", execution.getActivityName());

當執行在archive活動等待時,默認的signal會讓它 選擇第一個未命名的轉移.

execution.signal();
assertEquals("end", execution.getActivityName());

流程執行在客戶端的線程中. startProcessInstance方法只在到達evaluate活動時返回. 換句話說,ClientProcessDefinition.startProcessInstance和 ClientExecution.signal方法會一直堵塞直到 下一個等待狀態的到來.

13.2. 持久化執行模式

流程虛擬機也包含hibernate映射來保存流程定義和執行 在任何資料庫中.一個特定的會話外觀叫做ExecutionService 被提供給流程執行 在這樣一個持久化環境中.

兩個配置文件應該放在classpath下:一個環境配置文件 和一個hibernate.properties文件. 一個持久化執行模式的基礎配置,在一個標準Java環境 看起來像這樣:

environment.cfg.xml:

<jbpm-configuration>

<process-engine-context>

<deployer-manager>
<assign-file-type>
<file extension=".jpdl.xml" type="jpdl" />
</assign-file-type>
<parse-jpdl />
<check-process />
<check-problems />
<save />
</deployer-manager>

<process-service />
<execution-service />
<management-service />

<command-service>
<retry-interceptor />
<environment-interceptor />
<standard-transaction-interceptor />
</command-service>

<hibernate-configuration>
<properties resource="hibernate.properties" />
<mapping resource="jbpm.pvm.typedefs.hbm.xml" />
<mapping resource="jbpm.pvm.wire.hbm.xml" />
<mapping resource="jbpm.pvm.definition.hbm.xml" />
<mapping resource="jbpm.pvm.execution.hbm.xml" />
<mapping resource="jbpm.pvm.variable.hbm.xml" />
<mapping resource="jbpm.pvm.job.hbm.xml" />
<mapping resource="jbpm.jpdl.hbm.xml" />
<cache-configuration resource="jbpm.pvm.cache.xml"
usage="nonstrict-read-write" />
</hibernate-configuration>

<hibernate-session-factory />

<id-generator />
<types resource="jbpm.pvm.types.xml" />
<job-executor auto-start="false" />

</process-engine-context>

<transaction-context>
<hibernate-session />
<transaction />
<pvm-db-session />
<job-db-session />
<message-session />
</transaction-context>

</jbpm-configuration>

下一個,hibernate.properties像這樣:

hibernate.properties:

hibernate.dialect org.hibernate.dialect.HSQLDialect
hibernate.connection.driver_class org.hsqldb.jdbcDriver
hibernate.connection.url jdbc:hsqldb:mem:.
hibernate.connection.username sa
hibernate.connection.password
hibernate.hbm2ddl.auto create-drop
hibernate.cache.use_second_level_cache true
hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider
# hibernate.show_sql true
hibernate.format_sql true
hibernate.use_sql_comments true

然後你可以從環境工廠中像這樣獲得服務:

EnvironmentFactory environmentFactory = new PvmEnvironmentFactory("environment.cfg.xml");

ProcessService processService = environmentFactory.get(ProcessService.class);
ExecutionService executionService = environmentFactory.get(ExecutionService.class);
ManagementService managementService = environmentFactory.get(ManagementService.class);

ProcessService的責任是管理流程定義資源. 在我們可以啟動一個流程執行之前, 流程定義需要被發布到流程資源庫中. 流程定義可以使用不同的格式和不同的流程語言提供. 一個發布包含了流程定義信息,從不同的源文件中,像一個ZIP文件, 一個XML文件或一個流程定義對象. ProcessService.deploy方法會獲得一個發布 通過配置在配置文件里的所有發布器.

在這個例子中,我們通過代碼方式為發布 提供一個流程定義.

ClientProcessDefinition processDefinition = ProcessFactory.build("loan")
.activity("submit loan request").initial().behaviour(AutomaticActivity.class)
.transition().to("evaluate")
.activity("evaluate").behaviour(WaitState.class)
.transition("approve").to("wire money")
.transition("reject").to("end")
.activity("wire money").behaviour(AutomaticActivity.class)
.transition().to("archive")
.activity("archive").behaviour(WaitState.class)
.transition().to("end")
.activity("end").behaviour(WaitState.class)
.done();

Deployment deployment = new Deployment(processDefinition);
processService.deploy(deployment);

現在流程定義的一個版本保存到資料庫中. check-version發布器會把版本1 分配給存儲的流程定義.create-id發布器 會提取idloan:1 根據流程名稱和分配的版本.

再次發布流程會導致在資料庫中創建一個新流程定義. 但是一個增加的版本數會被分配. 出於版本化的目的,如果有相同的名字, 流程定義就會相同.

推薦用戶為所有流程執行提供key的引用. 啟動一個新流程執行像這樣:

Execution execution = executionService.startExecution("loan:1", "request7836");

返回值是一個execution介面,防止關係的嚮導. 那是服務方法外面,事務和hibernate會話沒有保證一直打開. 實際上,上面給出的默認的配置只保證 事務和會話在服務方法執行中是打開的. 服務方法外的關係導航可能引起一個hibernate的 LazyInitializationException. 但是當前的活動名稱還可以被驗證.

assertEquals("evaluate", execution.getActivityName());

生成可以被獲得的id也是非常重要的. 默認的id-generator會用來生成流程定義的id 給出的key來為流程執行生成一個唯一id,像這樣:

assertEquals("loan:1/request7836", execution.getId());

那個id必須提供給外部觸發器 像這樣處理流程執行:

executionService.signalExecution("loan:1/request7836", "approve");

關於服務介面的更多信息,關於如何運行在持久化模式下, 可以在包 org.jbpm.pvm 的api doc找到.

13.3. 嵌入執行模式

嵌入執行模式意味著路程的狀態保存在 一個用戶領域對象的字元串列中,比如一個loan.

public class Loan {

/** the loan process definition as a static resource */
private static final ClientProcessDefinition processDefinition = createLoanProcess();

private static ClientProcessDefinition createLoanProcess() {
ClientProcessDefinition processDefinition = ProcessFactory.build("loan")
.activity("submit loan request").initial().behaviour(AutomaticActivity.class)
.transition().to("evaluate")
.activity("evaluate").behaviour(WaitState.class)
.transition("approve").to("wire money")
.transition("reject").to("end")
.activity("wire money").behaviour(AutomaticActivity.class)
.transition().to("archive")
.activity("archive").behaviour(WaitState.class)
.transition().to("end")
.activity("end").behaviour(WaitState.class)
.done();

return processDefinition;
}

/** exposes the process definition to the execution hibernate type */
private static ClientProcessDefinition getProcessDefinition() {
return processDefinition;
}


long dbid;
String customer;
double amount;
ClientExecution execution;

/** constructor for persistence */
protected Loan() {
}

public Loan(String customer, double amount) {
this.customer = customer;
this.amount = amount;
this.execution = processDefinition.startProcessInstance();
}

public void approve() {
execution.signal("approve");
}

public void reject() {
execution.signal("reject");
}

public void archiveComplete() {
execution.signal();
}

public String getState() {
return execution.getActivityName();
}

...getters...
}

如果你暫時忽略加粗部分,你可以看到這是一個沒有任何奇異的POJO. 它只是一個bean,可以保存到hibernate中. 粗體部分展示了類的實現部分,這與流程和執行相關. 流程定義或者執行都沒有暴露給 Loan類的用戶.

每個Loan對象對應一個loan流程實例. Loan類的一些方法 對應外部觸發器, 這會在Loan對象的生命周期被觸發.

接下來我們演示如何使用這個類,為了開始,我們需要一個

hibernate.cfg.xml:

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>

<property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
<property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="hibernate.connection.url">jdbc:hsqldb:mem:.</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.hbm2ddl.auto">create</property>
<property name="hibernate.show_sql">true"</property>
<property name="hibernate.format_sql">true"</property>
<property name="hibernate.use_sql_comments">true"</property>

<mapping resource="Loan.hbm.xml"/>

</session-factory>
</hibernate-configuration>

和一個

Loan.hbm.xml:

<?xml version="1.0"?<


<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"<

<hibernate-mapping package="org.jbpm.pvm.api.db.embedded" default-access="field"<

<typedef name="execution" class="org.jbpm.pvm.internal.hibernate.ExecutionType" />

<class name="Loan" table="LOAN"<

<id name="dbid"<
<generator class="sequence"/>
</id<

<property name="execution" type="execution" />
<property name="customer" />
<property name="amount" />

</class<

</hibernate-mapping<

然後你可以在測試中像這樣使用Loan類

Configuration configuration = new Configuration();
configuration.configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();

// start a session/transaction
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();

Loan loan = new Loan("john doe", 234.0);
session.save(loan);
assertEquals("evaluate", loan.getState());

// start a new session/transaction
transaction.commit();
session.close();
session = sessionFactory.openSession();
transaction = session.beginTransaction();

loan = (Loan) session.get(Loan.class, loan.getDbid());
assertEquals("evaluate", loan.getState());
loan.approve();
assertEquals("archive", loan.getState());

// start a new session/transaction
transaction.commit();
session.close();

在執行這段代碼之後,這是在資料庫中的loan記錄:

圖 13.2. 資料庫中的貸款記錄


[火星人 ] jBPM-4.0中文開發指南-第13章 執行模式已經有693次圍觀

http://coctec.com/docs/java/show-post-61314.html