jbpm4.0:jBPM-4.0中文开发指南-第13章 执行模式

  第 13 章 执行模式

   这里有 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. 数据库中贷款记录



Tags:  jbpm4 jbpm4.0

延伸阅读

最新评论

发表评论