图 7-1 转换和其不同形式
关于流程定义xml表示和流程包的更多信息,参考第21章 jBPM流程定义语言(JPDL)。
更多的关于如部署流程包到数据库的信息可以在21.1.1 部署流程包 节找到。
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext(); try { // 调用持久化操作 } finally { jbpmContext.close();
}
|
<jbpm-configuration>
<jbpm-context> <service name='persistence' factory='org.jbpm.persistence.db.DbPersistenceServiceFactory' /> ... </jbpm-context> ...
</jbpm-configuration>
|
l 部署流程
l 开始一个新的流程执行
l 继续一个执行
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext(); try { ProcessDefinition processDefinition = ...; jbpmContext.deployProcessDefinition(processDefinition); } finally { jbpmContext.close();
}
|
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext(); try { String processName = ...; ProcessInstance processInstance = jbpmContext.newProcessInstance(processName); } finally { jbpmContext.close();
}
|
为了继续一个流程执行,我们需要从数据库中捕获流程实例、token或taskInstance,调用在POJO jBPM对象上的一些方法然后保存这些更新使这个流程实例再次进入数据库中。
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext(); try { long processInstanceId = ...; ProcessInstance processInstance = jbpmContext.loadProcessInstance(processInstanceId); processInstance.signal(); jbpmContext.save(processInstance); } finally { jbpmContext.close();
}
|
注意如果你用JbpmContext 的xxxForUpdate方法的话,一个明确的jbpmContext.save 方法调用就不再是必须的了,因为在关闭jbpmContext期间它将自动的调用。例如:假设我们想通知jBPM关于taskInstance已经完成了。注意任务实例完成能够触发执行继续所以与taskInstance 相关的processInstance必须被保存。最方便的方式是使用loadTaskInstanceForUpdate方法来做:
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext(); try { long taskInstanceId = ...; TaskInstance taskInstance = jbpmContext.loadTaskInstanceForUpdate(taskInstanceId); taskInstance.end(); } finally { jbpmContext.close();
}
|
JbpmConfiguration维护一系列的服务工厂。这些服务工厂在jbpm.cfg.xml文件中被配置正如上面显示的那样,而且是懒初始化的(instantiated lazy)。DbPersistenceServiceFactory只在它第一次需要的时候被初始化。在那以后,服务工厂被维护在JbpmConfiguration里。DbPersistenceServiceFactory管理hibernate 的SessionFactory。并且当第一次请求hibernate session工厂时它被懒创建(creat lazy)。
图 7-2 持久化关联类
在jbpmConfiguration.createJbpmContext()调用期间,只有JbpmContext被创建。那时没有更多的有关持久化的初始化被做。JbpmContext管理DbPersistenceService,它在第一次请求时被实例化。DbPersistenceService管理hibernate session。而且hibernate session是在DbPersistenceService内部被懒创建。结果,hibernate session将只有当第一个请求持久化的操作被调用且不会早于此请求的时候才被打开。
l 在你的应用服务器上配置一个DataSource
l 配置hibernate连接用数据源
l 使用窗口管理事务
l 在jBPM中禁止事务
在jBPM前端的无状态的session facade是个好的习惯。最容易的方式如何绑定jbpm事务到容器事务是要确信hibernate配置被jbpm引用的xa-datasource所使用。所以jbpm将使用它自己的hibernate session,那将只被1个jdbc连接和1个事务使用。
hibernate.connection.datasource= --数据源JNDI 名 — 例如: java:/DefaultDS |
更多的关于如何配置hibernate的jdbc连接的信息,参考hibernate参考文档, “Hibernate provided JDBC connections”。
更多 的关于如何在jboss中配置xa_datasource的信息,参考jboss应用服务器指导,“Configuring JDBC DataSources”。
在某些情况下,你已经有了一个hibernate session并且你要是想合并所有的持久化工作从jBPM进入那个hibernate session中。
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext(); try { jbpmContext.setSession(SessionFactory.getCurrentSession()); // jbpmContext 上的jBPM操作 } finally { jbpmContext.close();
}
|
jBPM的配置提供了jBPM创建hibernate session工厂、hibernate session、jdbc连接和jbpm必须服务等等的必要信息。但是所有的这些资源也能够被在程序中提供给jBPM。正好注入他们到jbpmContext中。被注入的资源总是在从jbpm配置信息创建资源之前被接受。
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext(); try { // 为了在他们被使用之前注入资源,你可以使用 jbpmContext.setConnection(connection); // 或 jbpmContext.setSession(session); // 或 jbpmContext.setSessionFactory(sessionFactory); } finally { jbpmContext.close();
}
|
DbPersistenceService维护hibernate session的延迟初始化。所有的数据库访问都是通过这个hibernate session来完成的。所有的查询和更新都是通过jBPM暴露的XxxSession类,像GraphSession、SchedulderSession、LoggingSession等等来完成的。这些session类使用hibernate的查询并且在相同的hibernate session下。
XxxxSession类也是可以通过JbpmContext 进行存取的。
重要:不要混用长短标签来配置工厂。参考:6.1 配置工厂。如果工厂只是一个类的新实例,你可以使用工厂的属性去引用工厂元素类名。但是如果工厂属性必须被配置的话,必须使用长标签而且factory和bean必须作为一个嵌套元素来组合使用。像这样:
<jbpm-context>
<service name="persistence"> <factory> <bean class="org.jbpm.persistence.db.DbPersistenceServiceFactory"> <field name="isTransactionEnabled"><false /></field> <field name="sessionFactoryJndiName"> <string value="java:/myHibSessFactJndiName" /> </field> <field name="dataSourceJndiName"> <string value="java:/myDataSourceJndiName" /> </field> </bean> </factory> </service> ... </jbpm-context> |
l isTransactionEnabled:缺省的,jBPM将开始一个hibernate事务当第一次捕获session并且如果jbpmContext被关闭时,hibernate事务将被结束。然后事务被提交或者是回滚都依赖于是否jbpmContext.setRollbackOnly被调用。isRollbackOnly属性在TxService中维护。为了禁止并限制jBPM使用hibernate管理事务。配置isTransactionEnabled属性为false像在上面的例子中的那样。这个属性只能控制jbpmContext的行为。你仍然可以直接使用API来调用DbPersistenceService.beginTransaction(),那就可以忽略isTransactionEnabled这个属性设置。更多的关于事务的信息,参考:7.3 Hibernate事务。
l sessionFactoryJndiName:缺省的,这个值是null,意味着session工厂不会被JNDI捕获。如果设置和session工厂是必须的去创建一个hibernate session的话,那么这个session工厂将从jndi中使用提供的JNDI命名被捕获。
<jbpm-configuration>
... <!-- configuration resource files pointing to default configuration files in jbpm-{version}.jar --> <string name='resource.hibernate.cfg.xml' value='hibernate.cfg.xml' /> <!-- <string name='resource.hibernate.properties' value='hibernate.properties' /> --> ...
</jbpm-configuration>
|
当这个属性 resource.hibernate.properties被指定时,资源文件中的属性将重写hibernate.cfg.xml中的所有属性。取代更新hibernate.cfg.xml文件指明数据库,hibernate属性能够方便的用于处理jbpm的升级:复制hibernate.cfg.xml文件就可以而不用非得修改它了。
请参考hibernate文档: http://www.hibernate.org/214.html
如果你想使用jBossCache来配置jBPM的话,看下jBPM配置wiki页面。
更多的关于在hibernate中配置cache provider的信息,去看hibernate文档,二缓存部分。
<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property> |
缺省情况下,jBPM将委托事务给hibernate并使用每事务模型session。jBPM将在一个hibernate session被打开时开始一个hibernate事务。这个将当持久化操作在jbpmContext上被调用时的第一次发生。这个事务将恰好在hibernate session关闭前被提交。那个将发生在jbpmContext.close()的内部。
为了限制jBPM调用hibernate API的事务方法,设置isTransactionEnabled为false,这个在上面的7.2.1 DbPersistenceServiceFactory部分被解释了。
<jbpm-context>
<service name="persistence"> <factory> <bean class="org.jbpm.persistence.db.DbPersistenceServiceFactory"> <field name="isTransactionEnabled"><false /></field> <field name="isCurrentSessionEnabled"><true /></field> <field name="sessionFactoryJndiName"> <string value="java:/myHibSessFactJndiName" /> </field> </bean> </factory> </service> ... </jbpm-context> |
然后你应该在你的hibernate session工厂中指定使用数据源并且绑定hibernate到事务管理器。确保你绑定数据源到一个XA数据源以防止你使用多个资源。更多关于绑定hibernate到你的事务管理器的信息,请查阅hibernate文档中的“事务策略配置”这一段。
<hibernate-configuration>
<session-factory> <!-- hibernate dialect --> <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property> <!-- DataSource properties (begin) --> <property name="hibernate.connection.datasource">java:/JbpmDS</property> <!-- JTA transaction properties (begin) --> <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property> <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property> <property name="jta.UserTransaction">java:comp/UserTransaction</property> ... </session-factory>
</hibernate-configuration>
|
<hibernate-configuration>
...
<!-- hql queries and type defs --> <mapping resource="org/jbpm/db/hibernate.queries.hbm.xml" />
...
</hibernate-configuration>
|
l 放jdbc驱动程序库到类路径上
l 更新jBPM使用的hibernate配置
l 在新数据库中创建模式(schema)
在开发中你可能感兴趣下列的hibernate配置:如果你设置hibernate配置属性'hibernate.hbm2ddl.auto' 为'create-drop'的话(例如在hibernate.cfg.xml中),这个模式将在应用第一次用到它时自动地在数据库中创建。当应用关闭时,这个模式将被丢弃。
l 从源文件(src/java.jbpm/...)处或jbpm jar包内部段复制jBPM的映射文件。
l 放这个拷贝到你的类路径上的任何地方
l 在你的hibernate.cfg.ml配置文件中更新引用为这些定制的映射文件。
<cache usage="nonstrict-read-write"/> |
因为流程定义从不会改变,所以保持它们在二级缓存中是好的。参考21.1.3 改变部署的流程定义。