1 swimlane:
具有流程角色的意思。一种多个任务由同一个actor执行的机制。swimlane中的第一个任务实例创建后分派时,会为该swimlane记住actor,后续的任务分派时将使用该actor。swimlane中的任务不能指定assignment,swimlane中的任务实例分派时,将由swimlane指定的assignment进行分派。swimlane中的第一个任务实例创建时,调用AssignmentHandler,此时传给AssignmentHandler的Assignable是一个SwimlaneInstance。
public interface AssignmentHandler extends Serializable {
void assign( Assignable assignable, ExecutionContext executionContext );
}
public interface Assignable {
public void setActorId(String actorId);
public void setPooledActors(String[] pooledActors);
}
TaskInstance和SwimlaneInstance都实现了Assignable。
2 assignment:
用于任务分派的元素。
actor-id:执行该任务的actor。
pooled-actors:可以执行该任务的actors。
两种分派模型:push和pull。
push:流程执行分派,调用Assignable.setActorId决定将该任务push到哪个user的任务列表。任务列表的获取:TaskMgmtSession.findTaskInstances(String actorId).
pull:该任务具有多个候选actor。由pool中的actor将任务pull进自己的任务列表。在pull之前任务对pool中的所有actor可见,pull后,actor-id变为pull的actor,并在pool中不可见。将actor-id置为null可以将该任务实例重新放回poll。调用Assignable.setPooledActors分派给pooledActors。
3 expression:
分派表达式。
identity comoponent:用户、组和许可权的管理,包括组织模型信息。
分派表达式示例:
<process-definition>
...
<task-node name='a'>
<task name='laundry'>
<assignment expression='previous --> group(hierarchy) --> member(boss)' />
</task>
<transition to='b' />
</task-node>
...
分派表达式语法:
first-term --> next-term --> next-term --> ... --> next-term
其中:
first-term ::= previous |
swimlane(swimlane-name) |
variable(variable-name) |
user(user-name) |
group(group-name)
next-term ::= group(group-type) |
member(role-name)
还可在action、delegation、decision condition中使用类似于JSP/JSF EL的表达式语言,如expression="#{myVar.handler[assignments].assign}" 。
4 delegation:
用来在流程执行过程中运行用户自定义代码的机制。可用于任务代理。
class(必需):完整类名。
config-type(可选):指定如何实例化和配置delegation对象。若没有则用默认constructor,并忽略配置信息。
field:configuration中的elementnames对应delegation中的域名;
示例:
public class MyAction implements ActionHandler {
// access specifiers can be private, default, protected or public
private String city;
Integer rounds;
...
}
对应的配置文件:
...
<action class="org.test.MyAction">
<city> Atlanta </city>
<rounds>5</rounds>
</action>
...
bean;constructor;configuration-property。
configuration(可选):xml文件,delegation配置信息。
5 start-state:
特殊node:启动节点。可以包含task、transition、event和exception-handler。
6 transition:
源节点是包含该transition的节点,目标节点由to指出。transition的名字是可选的。jBPM的路由功能依赖于transition名字的唯一性。但如果多个transition有相同的名字,将选择第一个。节点transition list中的第一个是其default transition。
7 task:
任务定义,指出如何创建和分派任务实例。可以在task-node,也可以在process-definition中定义。process-definition范围内task name必须唯一。
任务可以指定优先级。任务实例可以修改此优先级。
该任务可以属于一个swimlane,此时它的分派由对应的swimlane执行。
duedate指出任务的超时日期。
task的signalling属性指出当该任务实例完成时,可以发送一个signal给其token来继续流程的执行。task的blocking属性指出当该任务实例没完成之前,与之相关的token不能离开该task-node。默认设置是signalling和non-blocking。
8 task-controller:
可选。
任务创建时,可以用controller来移植任务实例变量;任务实例完成时,可以通过controller来向流程实例变量提交任务实例变量。
并不强迫一定要使用controller,仅当有下列需求时使用controller:
1) 创建流程实例变量在任务实例中的副本,使得对任务实例变量的改变不会影响流程实例变量。直到流程完成再将任务实例变量提交。
2) 流程实例变量与任务实例变量不是一一对应关系。例如三个流程变量“sales in january”、“sales in februry”和“sales in march”,在任务中可能需要用到的是这三个变量的平均值。
controller在流程变量(process context)和用户接口应用程序之间起一个桥的作用(如下图所示)。当创建任务实例时,controller负责从流程变量中摘录信息来创建任务变量。这些变量作为用户输入提供给用户接口应用。外部输入也存储在任务变量中。当任务结束时,controller负责用任务实例数据更新流程变量。
简单的一对一映射的例子如下:
<task name="clean ceiling">
<controller>
<variable name="a" access="read" mapped-name="x" />
<variable name="b" access="read,write,required" mapped-name="y" />
<variable name="c" access="read,write" />
</controller>
</task>
name属性指流程变量名,mapped-name指任务中的变量名。access属性指出是否在任务创建时复制变量,或是否在任务结束后写回流程,或是否是必须的。access是可选的,默认值是"read,write"。
如果简单的一一映射不能满足需要,可以自定义TaskControllerHandler接口的实现:
public interface TaskControllerHandler extends Serializable {
void initializeTaskVariables(TaskInstance taskInstance, ContextInstance contextInstance, Token token);
void submitTaskVariables(TaskInstance taskInstance, ContextInstance contextInstance, Token token);
}
并用如下方法定制自己的TaskControllerHandler实现:
<task name="clean ceiling">
<controller class="com.yourcom.CleanCeilingTaskControllerHandler">
-- here goes your task controller handler configuration --
</controller>
</task>
9 timer:
定时器。属性包括timer名、duedate、repeat和transition。transition指出定时器到时间时要执行该transition。
向节点加入timer最简单的方法是在节点定义中加入timer元素:
<state name='catch crooks'>
<timer name='reminder'
duedate='3 business hours'
repeat='10 business minutes'
transition='time-out-transition' >
<action class='the-remainder-action-class-name' />
</timer>
</state>
节点中指定的timer在离开该节点后不会执行。transition和action都是可选的。当执行一个timer会顺序发生如下事件:
1) 发送timer类型事件;
2) 如果指定了action,则执行该action;
3) 如果指定了transition,则通过该transition发送signal来恢复流程执行。
timer必须有唯一的名字,若没有指定timer名,将使用node名作为其名字。
timer由action创建和取消,分别是create-timer和cancel-timer。
10 action:
action可以放在event中,也可以放在node中。每个event都有一个action list,当发送一个event时,执行该event的action list中的所有action。event中的action执行不会影响流程执行控制流。node中的action则要负责流程执行的传递。
class指出action处理类,实现了ActionHandler。config-type指出如何配置该actionhandler类。如下示例:
public class RemoveEmployeeUpdate implements ActionHandler {
public void execute(ExecutionContext ctx) throws Exception {
String firedEmployee = (String) ctx.getContextInstance().
getVariable("fired employee");
Connection connection = ctx.getProcessInstance().
getJbpmSession().getSession().getConnection();
Statement statement = connection.createStatement();
statement.execute("DELETE FROM EMPLOYEE WHERE ...");
statement.execute();
statement.close();
}
}
对应流程定义:
<process-definition name="yearly evaluation">
...
<state name="fire employee">
<transition to="collect badge">
<action class="com.nomercy.hr.RemoveEmployeeUpdate" />
</transition>
</state>
<state name="collect badge">
...
</process-definition>
action的name和ref-name。ref-name可以放在任何能指定action的地方。ref-name的使用用来限制复杂action configuration的副本。或用于运行时action的执行的调度。
accept-propagated-events:是否允许事件沿着node—superstate—processdefinition进行传递。
11 event:
可以出现在process-definition、node和transition中。
属性由事件类型指出。有4种task-event类型:task-create、task-assign、task-start和task-end。一个事件对应有一个action list,当该事件发生时,执行list中的所有action。
可以定制自己的事件类型,通过GraphElement.fireEvent(String eventType, ExecutionContext executionContext)来发送事件。
12 script:
也是一种action,它用来执行beanshell script。默认情况下,script可以使用process、task、token、node、executeContext和taskInstance的所有variable作为自己的script variable,但script variable不能写回到process variable。
如下示例:
<process-definition>
<event type="node-enter">
<script>
System.out.println("this script is entering node "+node);
</script>
</event>
...
</process-definition>
可以在script中包含expression和variable子元素。variable元素的使用用来定制载入和存储变量的默认行为。如下示例:
<process-definition>
<event type="process-end">
<script>
<expression>
a = b + c;
</expression>
<variable name='XXX' access='write' mapped-name='a' />
<variable name='YYY' access='read' mapped-name='b' />
<variable name='ZZZ' access='read' mapped-name='c' />
</script>
</event>
...
</process-definition>
create-timer和cancel-timer是创建和取消定时器的action。
13 exception handler:
在process-definition、node和transition中可以指定一个exception handler list。每个exception handler都有一个action list。都发生exception时,在产生exception的delegation类所属层次结构中查找对应的exception-handler,找到则执行handler中的所有action。
与java异常处理机制不同,不能改变控制流。exception可以是caught,也可以是uncaught。exception可以由exception-handler caught。uncaught exception被抛给client。对于caught exception,图的执行会和没抛出exception一样继续执行。
在处理exception的action中,通过调用Token.setNode(Node node)可以将token放在图中的任意node。
14 node element
node
node类型的节点用于需要在node中执行用户自定义的代码。node类型节点有一个action,当执行到该节点时,执行action。actionhandler中的代码可以做任何你想做的事情,但要负责流程执行的继续。
所有节点类型都有name属性,async="true"时,表示流程可以异步执行。
state:
state本质上是一个wait state。它与task-node不同的地方是它不会创建任务实例。它可以用于与外部系统的交互。当进入该节点,向外部系统发送消息,然后等待,直到外部系统将响应消息发回该节点,导致调用token.signal(),从而触发流程的继续执行。
task-node:
任务分派节点。
task-node的signal属性值:
last
last-wait
first
first-wait
unsynchronized
never
create-tasks:boolean。default="true",该节点执行时是否创建任务实例。
end-tasks:boolean。default="false",该节点执行完后,若其中的任务实例没有end,是否将其end。
super-state:
一组节点的集合,可以嵌套,这给流程定义带来层次性结构。jBMP中可以将任意的节点组合成super-state。这些super-state通常代表应用的某个阶段。
superstate transition:所有离开该super-state的transition都可以由内部节点的token执行。transition可以到达superstate,此时token将被重定向到superstate的第一个节点。superstate外部的节点可以transition到内部节点,内部节点可以transition到外部节点,也可以到superstate自身。
superstate event:superstate专有的两个event:superstate-enter和superstate-leave。只要进入superstate就发送superstate-enter事件,只要离开superstate范围(不管是内部哪个node,只要是transition到外部node),就发送superstat-leave事件。
层次结构名:节点在节点集范围(流程或superstate)内,名字要唯一。可以通过层次名来引用。
<process-definition>
...
<super-state name="phase one">
<state name="preparation">
<transition to="../phase two/invite murphy"/>
</state>
</super-state>
<super-state name="phase two">
<state name="invite murphy"/>
</super-state>
...
</process-definition>
process-state:
用来执行子流程的节点。当进入该process-state,创建sub-process实例并执行,直到(default async="false")sub-process结束,才继续super process的执行。
一个process-state的例子:
<process-definition name="hire">
<start-state>
<transition to="initial interview" />
</start-state>
<process-state name="initial interview">
<sub-process name="interview" />
<variable name="a" access="read,write" mapped-name="aa" />
<variable name="b" access="read" mapped-name="bb" />
<transition to="..." />
</process-state>
...
</process-definition>
fork:
分支节点,将执行路径分解为多个并发执行路径,默认情况下,为每个离开该fork的transition创建一个子token,与到达该fork的token构成父子关系。
join:
默认情况下,到达join节点的token都必须有相同的父token,也就是这些token由同一个fork split出来。join负责end到达该节点的子token。当所有子token到达join,才继续父token的执行。join的leaving transition是唯一的。
decision:
判断节点。有两种判断模型,一种由process进行判断(在process-definition内),一种由外部实体(即不是process-definition的一部分)决定判断结果。
如果是流程决定判断,一种简单的办法是在transition中加入condition,condition是beanshell expression,它返回boolean值。运行时,decision节点在其leave transition中按它们定义顺序循环,直到找到第一个condition计算结果为true,take该transition。另一种办法是指定DecisionHandler,由该handler计算要take的transition返回给decision。
当由外部实体决定判断结果时,需要执行多次转换。即在decision前的wait state与外部实体交互,获取的结果进入decision进行判断。
end-state:
流程结束节点。