jBPM用户指南 第十章 上下文 (转载)

来源:互联网 发布:nginx 反向代理优化 编辑:程序博客网 时间:2024/04/28 21:24
第10章 上下文
上下文与流程变量有关,流程变量是维护与流程实例有关信息的“键-值”对,因为上下文必须存储在数据库中,所以使用会有一些约束。
10.1 访问变量
org.jbpm.context.exe.ContextInstance是提供流程变量服务的核心接口,你可以象如下这样从一个流程实例获取ContextInstance:
ProcessInstance processInstance = ...;
ContextInstance contextInstance = (ContextInstance) processInstance.getInstance(ContextInstance.class);
最基本的操作是:
void ContextInstance.setVariable(String variableName, Object value);
void ContextInstance.setVariable(String variableName, Object value, Token token);
Object ContextInstance.getVariable(String variableName);
Object ContextInstance.getVariable(String variableName, Token token);
变量名称是java.lang.String类型,默认情况下,Jbpm支持下列值类型:
l       java.lang.String
l       java.lang.Boolean
l       java.lang.Character
l       java.lang.Float
l       java.lang.Double
l       java.lang.Long
l       java.lang.Byte
l       java.lang.Short
l       java.lang.Integer
l       java.lang.Date
l       byte[]
l       java.io.Serializable
l       使用hibernate持久化的类
无类型的空值(null)也可以被持久化存储。
所有其他类型都可以毫无问题的被存储在流程变量里,但是当你试图保存流程实例时会导致一个异常。
要配置Jbpm存储变量中的hibernate持久化对象,请参考存储hibernate持久化对象部分。
10.2 变量生存期
变量不是必须在流程档案中声明。在运行时,你可以把任何java对象放进变量,如果这个变量不存在,它会被创建,就象使用一个普通的java.util.Map一样。
变量可以使用如下语句删除:
ContextInstance.deleteVariable(String variableName);
ContextInstance.deleteVariable(String variableName, Token token);
现在支持类型的自动转换,这意味着允许用一个不同类型的值来覆盖变量。当然,你应该尽量限制类型转换,因为这会造成比一个普通的列更新增加更多的数据库通信。
10.3 变量持久化
变量是流程实例的一部分,保存流程实例到数据库,使数据库与流程实例保持同步,作为保存(=更新)流程实例到数据库的结果,变量也将被从数据库创建、更新和删除。有关更多信息,请参考“第7章 持久化”。
10.4 变量范围
每个执行路径(参看:令牌)拥有它自己的一组流程变量,变量请求总是在令牌上发生。流程实例有一个令牌树(参看“第4章 面向图的编程”),当请求一个没有指定令牌的变量时,默认令牌是根令牌。
变量查询递归到给定令牌的父,这与编程语言中的变量范围是相似的。
当在令牌上设置一个不存在的变量时,变量在根令牌被创建,这就意味着每个变量默认都是整个流程范围的。如果想设置一个令牌局部变量,你必须明确使用如下语句创建:
ContextInstance.createVariable(String name, Object value, Token token);
 
10.4.1 变量重载
变量重载的意思是说,每个执行路径可以拥有它们自己的同名变量的拷贝,它们被看作是独立的,因此可以类型不同。当你通过同一转换发起多个并发的执行路径时,变量重载将会很有趣,区分这些执行路径的唯一之处就是它们各自独立的变量。
10.4.2 变量重写
变量重写的意思是说,在嵌套执行路径中的变量覆盖更高层执行路线中的变量。通常,嵌套执行路径涉及到并发:在分支和联合之间的执行路径是到达分支的执行路径的子(嵌套)。例如,如果你在流程实例范围有一个变量“contact”,你可以在嵌套的执行路径“shipping”和“billing”中重写这个变量。
10.4.3 任务实例变量范围
有关任务实例变量的更多信息,请参考“11.4 任务实例变量”。
10.5 临时变量
当流程实例被持久化到数据库时,正常的变量作为流程实例的一部分也被持久化。在某些情况下,你可能想在委托类中使用变量,但是你不想把它保存到数据库。例如,你想从Jbpm外部传递一个数据库连接到委托类,这可以使用临时变量来完成。
临时变量的生存期与流程实例(ProcessInstance)java对象一样。
由于这个自然性,临时变量与令牌无关,因此对于一个流程实例对象只有一个临时变量map。
临时变量使用上下文实例中它们自己的一组方法进行访问,并且不需要在processdefinition.xml中声明。
Object ContextInstance.getTransientVariable(String name);
void ContextInstance.setTransientVariable(String name, Object value);
 
10.6 定制变量持久化
变量保存到数据库中有两个步骤:
user-java-object <---> converter <---> variable instance
变量被保存在变量实例(VariableInstances)中,变量实例的成员使用hibernate被影射到数据库中的字段,在Jbpm的默认配置中,使用六种类型的变量实例:
l       DateInstance(使用一个影射到数据库中Types.TIMESTAMP的java.lang.Date字段)
l       DoubleInstance(使用一个影射到数据库中Types.DOUBLE的java.lang.Double字段)
l       StringInstance(使用一个影射到数据库中Types.VARCHAR的java.lang.String字段)
l       LongInstance(使用一个影射到数据库中Types.BIGINT的java.lang.Long字段)
l       HibernateLongInstance(用于可被hibernate化类型的长整型id字段,一个java.lang.Object字段被作为对一个数据库中hibernate实体引用的影射)
l       HibernateStringInstance(用于可被hibernate化类型的字符串id字段,一个java.lang.Object字段被作为对一个数据库中hibernate实体引用的影射)
转换器用来在java-user-objects和可以存储到变量实例的java对象之间进行转换,因此当一个流程变量使用如ContexInstance.setVariable(String variableName, Object value)被设置时,值将被使用转换器可选的转换,然后被转换的对象将被存储到变量实例。转换器实现了下面的接口:
public interface Converter extends Serializable {
 boolean supports(Object value);
 Object convert(Object o);
 Object revert(Object o);
}
转换器是可选的,它必须被Jbpm类加载器(参考16.2.1 Jbpm类加载器)可用。
user-java-objects被转换并且存储到变量实例的方式在文件org/jbpm/context/exe/jbpm.varmapping.xml中配置。要定制这个属性文件,需要把一个修改后的版本放在classpath根,就象在“6.2 配置文件”中解释的那样。属性文件的每行指定两个或三个用空格隔开的类名:user-java-object类名,可选的转换器类名和变量实例的类名。当你要引用你定制的转换器时,首先要确保它们在Jbpm的classpath(参考16.2.1 Jbpm类加载器)。当你要引用你定制的变量实例时,它们仍然需要在Jbpm的classpath(参考16.2.1 Jbpm类加载器),并且hibernate的影射文件org/jbpm/context/exe/VariableInstance.hbm.xml必须更新来包含定制的变量实例的子类。
例如,看一下下面的在文件org/jbpm.context/exe/jbpm.varmapping.xml中的片断。
    <jbpm-type>
      <matcher>
        <bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
          <field name="className"><string value="java.lang.Boolean" /></field>
        </bean>
      </matcher>
      <converter class="org.jbpm.context.exe.converter.BooleanToStringConverter" />
      <variable-instance class="org.jbpm.context.exe.variableinstance.StringInstance" />
    </jbpm-type>
这个片断指定了所有java.lang.Boolean类型的对象必须用转换器BooleanToStringConverter进行转换,并且转换结果对象(一个字符串)将被存储到一个StringInstance类型的变量实例对象里面。
如果没有指定转换器,则如下:
    <jbpm-type>
      <matcher>
        <bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
          <field name="className"><string value="java.lang.Long" /></field>
        </bean>
      </matcher>
      <variable-instance class="org.jbpm.context.exe.variableinstance.LongInstance" />
    </jbpm-type>
这表明变量中的Long类型对象存储在LongInstance类型变量实例中,不需要被转换。