学习jpdl

来源:百度文库 编辑:神马文学网 时间:2024/04/20 07:41:32
下面开始接触JBPM的JPDL部分:
在jpdl参考手册中主要介绍了processdefinition.xml文件的格式(schema)
一、Process archive:
如前面所描述的,process archive是商务流程的规则描述。它被打成jar包,通常以扩展名.par结束,jbpm识别一个流程需要三种类型的文件数据:
1、  业务流程的正式声明:在jpdl中,是以processdefinition.xml文件来表达。这一章节我们就来解析这个文件的格式。
2、  设计逻辑:在流程上加上规划逻辑这些也是在processdefinition.xml中给予描述的,在process archive中可以嵌套java-classes。所有在process archive中的classes应该放在子目录/classes中。
3、  其他资源文件。作为工作流引擎的客户端,在运行时你可能想要在流程中包含一些资源文件的变量。例如。窗体(form)的描述与某人执行任务相关联。Jbpm不能在你想要包含在一个流程定义中的资源文件的类型上做任何手脚。
二、version机制(此处versioning可以大致理解为:一个process archive部署后转变成过程定义的过程。)(此部分需要参考原文理解。感觉不对劲)
作为最最基本的,jbpm的翻译机制遵从下面原理:
l     每次process archive部署的时候,一个新的流程定义就在jbpm数据库中被创建。
l     在部署的时候,jbpm 安排一个version号码(数字)给过程定义。只有当过程名与被定义的号相同时候才会执行Process archives。为了实现安排version号码,如果它是第一个version jbpm采取1+(the highest version number of the current process definitions with the same name)或者1。从jbpm-api中可以通过一个给定的name查找最近的过程定义。
l     在一个给定的定义执行某一个过程实例,过程实例将会(等到同个定义结束前)一直在这个定义中保持执行状态。
l     通过这种方式能通过最近定义启动过程并且在相同定义中的完整的生命周期中保持运行状态。
l     注意:jbpm可以把一个设计的程序逻辑与一个过程相关联起来。通过在process archive中包含类文件,jbpm将会对于每个过程定义把classes分离出来。
三、Processdefinition.xml格式
文档类型定义:
"-//jBpm/jBpm Mapping DTD 2.0 beta3//EN"
"http://jbpm.org/dtd/processdefinition-2.0-beta3.dtd">
the document type definition of processdefinition.xml
过程定义:
swimlane*,
type*,
start-state,
( state |
milestone |
process-state |
decision |
fork |
join
)*,
end-state,
action*  ) >

dtd fragment for process-definition
状态:


dtd fragment for a state
在JBPM中,状态(state)这个术语与FSM(有限状态机)和UML状态图中有着同样的意思。
对商务流程进行建模的目的就是创建一个软件系统。我们考虑到过程定义是软件系统建立的一部分。所以jbpm中的状态术语是以一个软件系统的角度来解释的。
状态是jbpm的核心概念。在jbpm中当开始模仿一个流程,首要需要考虑的事情就是过程的状态。状态将成为你所设计的过程的基本框架。
以状态概念为核心的另外一个特殊原因是:状态在程序语言中没有容易重复混淆的概念。一个软件程序或者运行或者不运行。一个有代表性的商业过程都会与被分别执行的所设计的逻辑部分关联。Jbpm允许在相关联的程序逻辑中对状态建模。
Jpdl也在状态之间定义了变迁,决定,分支,合并,milestone(flow)。需要注意的,控制流定义在状态与状态之间。无论什么情况下,一个正常的设计逻辑是更合适的,过程开发人员就能够在一个过程事件上指定一个action。Jbpl与其他过程定义语言如bpel等之间的区别之一是,jpdl具备以状态管理方式对java进行扩展和与程序语言最小交叠性的能力。
委派(assignment):

assignment (optional|required) #IMPLIED
authentication (optional|required|verify) #IMPLIED >
dtd fragment for an assignment
当一个流程执行到某种状态时候,工作流引擎将会等到一个外部的trigger(通过调用jbpm的api,ExecutionService.endOfState(…))。在这个方法里面,jbpm将会算出流程实例的下一个状态。
所以一个状态能够依赖于一个外部参与者。外部参与者可以是一个人也可以是某个系统。有许多种方式来实现业务流程中的状态与任务相关联。这些任务基本上可以分为两组:
1、            基于客户端的委派
在这种策略中,jbpm的用户管理他们自己用户的任务列表。在这种情况,jbpm只是用一个执行引擎来控管有限状态机。Jbpm的职责是计算并且追踪过程执行中的状态,然而客户端的职责就是确保每个人知道做了什么。然后客户端一般就是在一个给定的状态中找到过程实例(或者说tokens)
2、            基于流程的委派
(在jbpm2.0 beta3之前支持这种委派策略)
在这种委派策略中,jbpm将会担负给参与者安排状态并且追踪任务列表的职责。在jbpm中,流程在执行过程中是以一个token来进行跟踪的。一个token有一个指针来指向状态和一个参与者。在jbpm中一个参与者总是引用java.lant.string。为了详细说明jbpm如何必须安排tokens给参与者们,一些事件与此相关。接下来一个一个介绍:
只要一个客户端启动一个过程实例或者发出结束状态的信号,jbpm都会计算过程实例的下一个状态。
首要的事情是关于这些api方法中的第一个参数:参与者。这个参与用来识别谁来执行。
在启动一个新的过程实例的情况下,一个root-token在开始状态中被创建好。在结束一个状态的情况下,一个tokenid需要以一个某种状态中的参数形式指定。然后,jbpm将会开始为token计算下一个新状态。为了简单起见,我们忽略并发这种情况。Token将会经历变迁和节点,然后抵达下一个状态节点。在那时,一个token需要安排一个参与者。选择一个参与者之后,jbpm将通过token和调用的方法(开始过程实例或者结束状态)的返回值进行关联选择的参与者
所以当一个状态中的token具备有一个参与者时,那就意味着过程实例的执行是在等待这个参与者提供一个外部trigger给jbpm引擎。在这种情形下,过程中的状态对应一个用户的任务,jbpm通过检索所有已经安排给指定的参与者的tokens计算任务列表。现在,参与者能够从列表中选择一个token和发出结束状态信号量。
Assignmentn(委派)有许多属性:assignment和authentication。Assingement属性可以有两个值:optional和required。Required意思指当执行到某一个状态时,jbpm将会检测是否把一个token安排了一个参与者。如果非法则会抛出AssignmentException的异常。如果assingment是optional(=default),当到达一个状态时jbpm就允许离开一个未安排的token。属性authentication指定约束条件来限定哪个参与者可以发出结束状态的信号。参与者通过endOfState方法中的参数actorid来指定。如果optional=default意思指对于指定谁来担当结束状态并不是必须的。Required意味着一个参与者需要被指定。Vertify意味着结束状态只可以安排给已经安排token的参与者。
更多信息请查看群组委派。查看faqs。
Swimlane


dtd fragment for swimlane
非常典型的情况,一个人具备一个流程中多个状态的职责。在jbpm中通过创建一个swimlane并且通过swimlane安排状态给参与者(actor)。一个业务流程中的swimlane可以被看做为一个针对参与者的角色名字。Jbpm对swimlane的解释与UML1.5中的术语swimlane解释一致。首次执行到达一个状态,给定一个swimlane,就会算出参与者。
public interface AssignmentHandler {
String selectActor( AssignmentContext assignerContext );
}
theAssignmentHandler interface
在swimalne中的delegation标签指向一个AssignmentHandler的具体实现。
然后那个参与者(actor)以swimlane中同名的方式被存储为过程变量。下次当一个process archives在一个状态,利用swimlane,jbpm引擎将会检测变量并且安排token给参与者(存储在变量中的)
计算的结果是存储一个swimlane同名的过程变量。所以当下一个状态到达相同的swimlane时,状态就会安排给相同的actor,而不再用AssignmentHandler 。因为在swimlane和参与者之间的关联已经存储在变量中,而且可以通过更新变量来改变swimlane参与者(actor)之间的关联关系。
变量和类型:





dtd fragment for type and variable
一个是变量是一种key-value对。它与过程实例(一次过程执行)相关联。Key是java.lang.string,value是任何java类型的任何pojo。所以任何是java类型,即使不给jbpm知道也能被应用到变量中。
变量存储过程实例的上下文信息(context)。变量可以通过下面几种方式进行设置读取:
ExecutionService.startProcessInstance( String actorId, Long definitionId, Map variables, String transitionName )
ExecutionService.endOfState( String actorId, Long tokenId, Map variables, String transitionName )
ExecutionService.setVariables( String actorId, Long tokenId, Map variables )
ExecutionContext.setVariable( String name, Object value )
ExecutionService.getVariables( String actorId, Long tokenId )
ExecutionContext.getVariable( String name )
当设计变量时候,jbpm尽量模仿java.util.map的语义。这一点可以通过jbpm-api来了解。也就是说一个变量只能当它被插入时被赋值,任何java类型都可以作为变量中的value。
一个type描述jbpm如何存储变量的值到数据库中。Jbpm有一个文本域用来存储值,中间以serializer来实现文本和对象之间的转换。
public interface Serializer {
String serialize( Object object );
Object deserialize( String text );
}
theSerializer interface
一个type 可以被看做一个serializer的引用。Jbpm包含了一些默认serializer的实现,其中包括下面java类型:
java.lang.String
java.lang.Long
java.lang.Double
by default supported java-types
变量类型匹配:
Java类型声明的变量已经被默认支持,而不用在processdefinition.xml声明。Jbpm有个自动转换机制:当一个变量初始化后,jbpm按照下面步骤,首先检测java类型。如果它默认被java支持,那么就可以正常使用,否则,jbpm检查声明的类型是否与processdefinition.xml中java-type属性定义的变量是否一致。在匹配过程中jbpm也考虑变量值的父类。如果没有找不到这种类型,jbpm就把这样的变量作为transient(瞬间)变量对待。为了避免jbpm不得不执行匹配过程,你可以把变量指定到它各自类型中去。
Transient(瞬间)变量:
一些变量并不需要做持久层处理存储在数据库中,jbpm支持瞬时变量。这样的变量不存储到数据库中并且只可以在jbpm-api的方法中使用。换句话说,瞬时变量的使用范围是:jbpm-api的方法。
开始状态:

swimlane CDATA #IMPLIED >
dtd fragment for start-state
开始状态是一个过程中的唯一状态,所有的过程实例从这里开始,注意在过程实例开始的时刻你能够把变量放在过程当中了。另外重点的概念是你能够有多个从开始状态出发的变迁,这样的话,就需要你指定哪个变迁是你启动过程实例时候需要执行的。
milestone:


dtd fragment for a milestone
一个milestone是一种特殊的状态,它用来处理两个并发事件中的同步的作用。一个milestone可以被应用在下面情形:一条执行路径需要等待另外一个执行路径上的事件。如果milestone没有到达,接下来的执行就必须在milestone处等待,知道另外一个并发路径到达的时候,才可继续执行。如果milestone已经到达了(条件具备了),接下来的执行就是通过这个milestone状态。关于milestone的更多信息和图形请参看工作流模式。一个milestone与一或多个actions(用信号通知milestones到达)相关联。那些actions能够用默认ActionHandler:org.jbpm.delegation.action.MilestoneReachdActionHandler在流程中建模。所以actions(发信号给jbpm引擎告诉它一个milestone已经到达)能够像下面这样在processdefition.xml中调度:
...



...



theMilestone



...
modelling a milestone in the processdefinition.xml
process-state:


dtd fragment for a process-state
一个process-state符合父过程的invocation。父过程执行到一个procee-state时候就开始一个子过程的执行。过程残留在process-state中用以子过程的持续。当一个子过程完成后,就从一个process-state中离开了。
Decision:


dtd fragment for a decision
一个decision用以决定在多个执行路径中哪个才可以被执行。如果你是一个程序员,把它可以理解成if-then=else结构即可,当然。一个decision能够具有许多离开的变迁。
需要注意的是一个decision对某个情况建模,在这里工作流引擎根据上下文(=variables)和一些其他外部资源决定哪个路由可以被接受。作为可供选择的(可以替代的做法),你设计从一个状态出发具备多个变迁。在那种情况下,jbpm客户端必须通过调用以一个选择变迁名字作为一个参数的endOfState方法决定哪个变迁被执行。
Fork(分支):

corresponding-join CDATA #IMPLIED>
dtd fragment for a fork
这个比较好理解,定义一般普通的fork行为一般是通过ForkHandler接口。但是默认行为(当在fork中没有delegetion时候)是fork的每个变迁都将获得一个子token。所以仅仅对一些高级外来的并发,你才需要实现ForkHandler.
一般情况下,一个fork会有一个相关的join。这个join定义个并发的block。默认下fork和join仅支持严格的嵌套,并且默认情况不支持绕过并发block边界的变迁。
public interface ForkHandler {
void fork( ForkContext forkContext ) throws ExecutionException;
}
the ForkHandler interface
join:

corresponding-fork CDATA #IMPLIED>
dtd fragment for a join
一个fork joins用于多条路径执行,用JoinHandler接口指定普通的join行为。但是默认情况下(没有delegation)是所有fork上的子token合并。最后token到达join将会触发父token最后引发join上的离开变迁。所以仅仅高级外来的并发你才需要实现JoinHandler.
约束:一个join只能有一个离开变迁。
public interface JoinHandler {
void join( JoinContext joinContext ) throws ExecutionException;
}
the JoinHandler interface
结束状态:


dtd fragment for end-state
一个过程定义有一个精确的结束状态。当一个过程实例执行到一个结束状态时候,这个过程实例就结束了。
变迁(transition):

to   CDATA #REQUIRED>
dtd fragment for a transition
变迁用来指定节点之间的连接。变迁元素应该放在node里面,那么这个变迁就会从这个节点出离开。
Action:

state-enter|state-leave|state-after-assignment|
milestone-enter|milestone-leave|
decision-enter|decision-leave|
fork-enter|fork-every-leave|
join-every-enter|join-leave|
transition) #IMPLIED>
dtd fragment for an action
一个action是一段java代码。在过程执行期间在一些事件基础之上action在工作流引擎上执行。
Action总是被定义成一个过程定义元素(process-definition, state, transition, decision, ...)的子元素。当action执行的时候,父元素会在过程执行时候外加一些事件类型来定义精确时刻。可以想象得到,一个action的可能事件类型依赖于action被包含进去的元素。事件类型名字(event-type-names)被暗示出是他们应用到的元素(理解有误)。在javadoc中有事件类型,可以进行查看。
public interface ActionHandler {
void execute( ExecutionContext executionContext );
}
the ActionHandler interface
delegation:


dtd fragment for a delegation
解释在约束元素和delegation 类必须实现的接口之间的关联。
四、其他process archive文件
当一个process archive被部署,processdefinition.xml将被解析并且把信息存储到jbpm数据库中去。所有其他的文件或者被存储在数据库中或者文件系统,与被创建的过程定义相关联。作为一jbpm api的客户端你能够通过ExecutionReadService.getFile( Long processDefinitionId, String fileName )访问这些文件。
一个process archive和一个过程定义(process definition)之间的区别参看versioning mechanism。