好文档 - 专业文书写作范文服务资料分享网站

深入浅出 jBPM 电子书

天下 分享 时间: 加入收藏 我要投稿 点赞

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中的片断。

class=\

class=\/>

class=\

这个片断指定了所有java.lang.Boolean类型的对象必须用转换器

BooleanToStringConverter进行转换,并且转换结果对象(一个字符串)将被存储到一个StringInstance类型的变量实例对象里面。

如果没有指定转换器,则如下:

class=\

class=\

这表明变量中的Long类型对象存储在LongInstance类型变量实例中,不需要被转换。

第11章 任务管理

Jbpm的核心业务是持久化流程执行的能力,对于管理任务和个人任务清单来说这是一个非常重要的特性,Jbpm允许指定一段软件描述所有人的任务中处于等待状态的流程。

11.1 任务

任务是流程定义的一部分,它们定义了在流程执行期间任务实例怎样被创建和分配。 任务可以在task-node和process-definition中定义,通常使用的方式是在一个task-node里定义一个或多个任务,这种情况下,task-node代表一个将由用户完成的任务,

并且流程执行将一直等待直到参与者完成这个任务,当参与者完成任务时,流程执行将继续。当在一个task-node中指定多个任务时,默认的行为是等待所有任务完成。

任务也可以被指定在process-definition。指定在process-definition的任务可以通过名称查找到并且在task-node里引用或者在内部动作中使用。事实上,所有给定名称的任务(包括在task-node中定义的任务)都可以在流程定义(process-definition)中通过名字查找到。

任务名称在整个流程定义中必须是唯一的。任务可以被指定一个优先级,这个优先级在任务的实例创建时将被作为每个任务实例的初始优先级,任务实例的初始优先级可以在以后被修改。

11.2 任务实例

任务实例可以被分配一个actorId(java.lang.String)。所有的任务实例被存储在数据库中的一张表里面(JBPM_TASKINSTANCE),通过查询这张表可以得到给定actorId的所有任务实例,进而获取特定用户的任务清单。

Jbpm的任务清单机制可以组合Jbpm任务和其他任务,甚至那些任务与流程执行毫不相干,这样,Jbpm开发者可以很方便的组合Jbpm流程任务和其他应用的任务到一个集中的任务清单仓库中。

11.2.1 任务实例生命周期

任务实例的生命周期是很直观的:创建后,任务实例可以被随意地开始,然后任务实例可以被结束,这意味着任务实例被标记为完成。

注意,为了灵活性,分配不是生命周期的一部分,所以任务实例可以被分配也可以不被分配,任务实例的分配不会影响任务实例的生命周期。

任务实例典型的创建是通过流程执行进入一个task-node(使用方法TaskMgmtInstance.createTaskInstance(…)),然后,用户接口组件会使用

TaskMgmtSession.findTaskInstancesByActorId(…)查询数据库获取任务列表,然后,在收集了用户输入后,UI组件调用TaskInstance.assign(String)、TaskInstance.start()或者TaskInstance.end(…)。

任务实例依靠日期属性维护它的状态:创建、开始和结束。这些属性可以通过任务实例上它们各自的getter方法访问。

通常,完成的任务实例用一个结束日期做了标记,所以它们不能被以后的任务列表查询获取,但是它们仍然存在于JBPM_TASKINSTANCE表中。

11.2.2 任务实例和图执行

任务实例是参与者任务清单(tasklist)中的项目,任务实例可以作为信号,当一个信号任务实例完成时,可以发送一个信号到它的令牌继续流程执行。任务实例可以被阻塞,这意味着在任务实例完成之前相关令牌(=执行路径)不允许离开任务节点。默认情况下,任务实例是信号非阻塞的。

如果多于一个任务实例与一个任务节点关联,流程开发者可以指定任务实例的完成怎样影响流程的继续。下面是可以给任务节点的signal属性设置的值:

l last:这是默认值。当最后一个任务实例完成时继续执行;当在节点入口处没有任务创建时,继

续执行。

l last-wait:当最后一个任务实例完成时继续执行;当在节点入口处没有任务创建时,执行在任

务节点等待,直到任务被创建。

l first:当第一个任务实例完成时继续执行;当在节点入口处没有任务创建时,继续执行。

l first-wait:当第一个任务实例完成时继续执行;当在节点入口处没有任务创建时,执行在任务

节点等待,直到任务被创建。

l unsynchronized:总是继续执行,不管任务是否创建和完成。 l never:执行不再继续,不管任务是否创建和完成。

任务实例可以基于运行时的计算创建,如果那样的话,需要添加一个ActionHandler到任务节点的node-enter事件,并且设置属性create-tasks=“false”。下面是这样一个动作的实现例子:

public class CreateTasks implements ActionHandler {

public void execute(ExecutionContext executionContext) throws Exception {

Token token = executionContext.getToken(); TaskMgmtInstance tmi =

executionContext.getTaskMgmtInstance();

TaskNode taskNode = (TaskNode) executionContext.getNode(); Task changeNappy = taskNode.getTask(\

// 现在, 相同任务的两个任务实例被创建

tmi.createTaskInstance(changeNappy, token); tmi.createTaskInstance(changeNappy, token); } }

如示例所展示,任务可以在指定的任务节点中创建,它们也可以被指定到

process-definition,并且从TaskMgmtDefinition获取。TaskMgmtDefinition用任务管理信息扩展了ProcessDefinition。

标识任务示例完成的API是TaskInstance.end(),你可以在end方法中指定一个转换,如果这个任务的完成会触发继续执行,则会通过指定的转换离开任务节点。

11.3 分配

流程定义包含任务节点,任务节点(task-node)包含一个或多个任务,任务作为流程定义的一部分是静态描述。在运行时,任务导致任务实例的创建,一个任务实例对应某人任务列表中的一个入口。

在Jbpm中,可以结合使用推模式和拉模式(见下文)的任务分配。流程可以计算任务的责任人,并把它推到他/她的任务清单里;或者,任务可以被分配到参与者池,这种情况下,池中的每个参与者都可以拉出任务并把它放入参与者的个人任务清单。

11.3.1 分配接口

通过接口AssignmentHandler进行任务实例分配:

public interface AssignmentHandler extends Serializable { void assign( Assignable assignable, ExecutionContext executionContext ); }

当任务实例被创建时分配处理的实现被调用,在那时,任务实例可以被分配到一个或多个参与者。AssignmentHandler实现将调用分配方法(setActorId或setPooledActors)分配任务,可以分配一个任务实例或者一个泳道实例swimlaneInstance(=流程角色)。

public interface Assignable {

public void setActorId(String actorId);

public void setPooledActors(String[] pooledActors); }

任务实例和泳道实例都可以被分配到一个用户或者共享参与者。分配任务实例到一个用户,调用Assignable.setActorId(String actorId);分配任务实例到候选的共享参与者,调用Assignable.setPooledActors(String[] actorIds)。

流程定义中的每个任务都可以与一个分配处理实现相关联,用来完成运行时的任务分配。 当流程中的多个任务将要分配给相同的人或者参与者组时,考虑使用泳道。 考虑到AssignmentHandler的重用,每个AssignmentHandler的使用可以在processdefinition.xml中配置。请参考“16.2 委托”了解怎样添加分配处理配置的更多信息。

11.3.2 分配数据模型

下面是管理分配任务实例和泳道实例到参与者的数据模型,每个任务实例拥有一个actorId或一组被共享的参与者。

图 11.1 分配模型类图

actorId对任务负责,而共享的参与者表示候选者集合,如果它们获取任务,则可以负责任务。actorId和共享参与者具体使用哪个是可选的,两者也可以结合使用。

11.3.3 推模式

任务实例的actorId表明对给定任务负责,而任务实例的共享参与者是任务的候选参与者。典型情况下,任务实例的actorId指向一个用户,共享参与者可以指向多个用户和/或用户组。

用户的任务清单是所有以用户作为actorId的任务实例,这个清单可以使用TaskMgmtSession.findTaskInstances(String actorId)获得。

11.3.4 拉模式

另一方面,共享的任务(译者注:共享任务即不仅是由一个用户负责的)是提供给共享参与者中所引用的用户的。获取共享任务一般需要两步操作:1)从身份组件中获取给定用户的所有组2)为结合了用户的actorId和指向用户组的actorId获取所有共享任务清单(译者注:

深入浅出 jBPM 电子书

ObjectContextInstance.getTransientVariable(Stringname);voidContextInstance.setTransientVariable(Stringname,Objectvalue);10.6定制变量持久化变量保存到数据库中有两个步骤:use
推荐度:
点击下载文档文档为doc格式
8l9bb1yjqg01k8300sny
领取福利

微信扫码领取福利

微信扫码分享