这里有 3种基本流程执行模式:对象持久化和嵌入 对于持久化和嵌入执行模式 流程执行必须在个事务中执行在那种情况 流程执行必须放在个环境内部 环境将用来绑定流程执行更新到个应用事务事务中 环境可以被用来绑定比如个JDBC连接 JTABMTSpring事务等等
13.1. 对象执行模式
对象执行模式是使用流程虚拟机最简单形式 这意味着通过客户端API直接使用流程定义和执行对象 让我们通过个例子演示这个 我们通过创建个ClientProcessDefinition开始看起来像这样:
对象执行模式是使用流程虚拟机最简单形式 这意味着通过客户端API直接使用流程定义和执行对象 让我们通过个例子演示这个 我们通过创建个ClientProcessDefinition开始看起来像这样:
图 13.1. 贷款流程
ClientProcessDefinition processDefinition = ProcessFactory.build("loan")
.activity("submit loan request").initial.behaviour(AutomaticActivity.)
.transition.to("evaluate")
.activity("evaluate").behaviour(WaitState.)
.transition("approve").to("wire money")
.transition("reject").to("end")
.activity("wire money").behaviour(AutomaticActivity.)
.transition.to("archive")
.activity("archive").behaviour(WaitState.)
.transition.to("end")
.activity("end").behaviour(WaitState.)
.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 被提供给流程执行 在这样个持久化环境中
两个配置文件应该放在path下:个环境配置文件 和个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-erceptor />
<environment-erceptor />
<standard-transaction-erceptor />
</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_ 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_ org.hibernate.cache.HashtableCacheProvider
# hibernate.show_sql true
hibernate.format_sql true
hibernate.use_sql_comments true
然后你可以从环境工厂中像这样获得服务:
EnvironmentFactory environmentFactory = PvmEnvironmentFactory("environment.cfg.xml");
ProcessService processService = environmentFactory.get(ProcessService.);
ExecutionService executionService = environmentFactory.get(ExecutionService.);
ManagementService managementService = environmentFactory.get(ManagementService.);
ProcessService责任是管理流程定义资源 在我们可以启动个流程执行的前 流程定义需要被发布到流程资源库中 流程定义可以使用区别格式和区别流程语言提供 个发布包含了流程定义信息从区别源文件中像个ZIP文件 个XML文件或个流程定义对象 ProcessService.deploy思路方法会获得个发布 通过配置在配置文件里所有发布器
在这个例子中我们通过代码方式为发布 提供个流程定义
ClientProcessDefinition processDefinition = ProcessFactory.build("loan")
.activity("submit loan request").initial.behaviour(AutomaticActivity.)
.transition.to("evaluate")
.activity("evaluate").behaviour(WaitState.)
.transition("approve").to("wire money")
.transition("reject").to("end")
.activity("wire money").behaviour(AutomaticActivity.)
.transition.to("archive")
.activity("archive").behaviour(WaitState.)
.transition.to("end")
.activity("end").behaviour(WaitState.)
.done;
Deployment deployment = 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 Loan {
/** the loan process definition as a resource */
private final ClientProcessDefinition processDefinition = createLoanProcess;
private ClientProcessDefinition createLoanProcess {
ClientProcessDefinition processDefinition = ProcessFactory.build("loan")
.activity("submit loan request").initial.behaviour(AutomaticActivity.)
.transition.to("evaluate")
.activity("evaluate").behaviour(WaitState.)
.transition("approve").to("wire money")
.transition("reject").to("end")
.activity("wire money").behaviour(AutomaticActivity.)
.transition.to("archive")
.activity("archive").behaviour(WaitState.)
.transition.to("end")
.activity("end").behaviour(WaitState.)
.done;
processDefinition;
}
/** exposes the process definition to the execution hibernate type */
private ClientProcessDefinition getProcessDefinition {
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 {
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_">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" ="org.jbpm.pvm.ernal.hibernate.ExecutionType" />
< name="Loan" table="LOAN"<
<id name="dbid"<
<generator ="sequence"/>
</id<
<property name="execution" type="execution" />
<property name="customer" />
<property name="amount" />
</<
</hibernate-mapping<
然后你可以在测试中像这样使用Loan类
Configuration configuration = Configuration;
configuration.configure;
SessionFactory sessionFactory = configuration.buildSessionFactory;
// start a session/transaction
Session session = sessionFactory.openSession;
Transaction transaction = session.beginTransaction;
Loan loan = Loan("john doe", 234.0);
session.save(loan);
assertEquals("evaluate", loan.getState);
// start a session/transaction
transaction.commit;
session.close;
session = sessionFactory.openSession;
transaction = session.beginTransaction;
loan = (Loan) session.get(Loan., loan.getDbid);
assertEquals("evaluate", loan.getState);
loan.approve;
assertEquals("archive", loan.getState);
// start a session/transaction
transaction.commit;
session.close;
在执行这段代码的后这是在数据库中loan记录:
图 13.2. 数据库中贷款记录
最新评论