jBPM3 vs jBPM4
JBoss Goup
目前已经发布了
jBPM4 Alpha1
版本,在版本
4
中最大的变化就是引入
PVM
(流程虚拟机)的概念,而引擎内部的调度算法中重要的
Token
机制,在新版中也去掉了,纵观整个代码,变化可以说非常的大,笔者接下来就试着来比较一下这种变化,让大家能有个直观的认识。当然
Jbpm4
在
JBoss
的官方网站上的
Road map
中,在今年的
7
月
1
号才会发布第一个正式版本,因此后续可能还会有变化。
1、
流程定义对象的变化:
Jbpm3
流程定义对象关系图:
图一 jbpm3流程定义对象关系图
从上图我们可以看出这
jbpm3
中,
GraphElement
是流程图中所有流程元素的父对象,而整个流程是由
ProcessDefinition
、
Node
、
Transition
三个主要对象构成;
图二 PVM实体对象关系图
从上图可以看出,由于
PVM
概念的引入,所以在
jbpm3
中的
Graph
包在
jbpm4
中被移除了。在
pvm
中,在设计期,所有节点元素的父类为
ProcessElementImpl
,流程的主要组成元素
Nodelmpl
、
TransitionImpl
、
ProcessDefinitionImpl
、
EventImpl
则都直接或间接继承自
ProcessElementImpl
。在运行期:
jbpm4
把流程的运行期行为定义为执行行为(
ExecutionImpl
)及原子操作行为(
AtomicOperation
,其具体实现为
ExecuteNode
、
ProceedToDestination
、
TakeTranstion
、
MoveToParentNode
、
MoveToChildNode
、
signal
),其中
ExecutionImpl
是流程实例、活动实例、事件监听器的所有执行期行为的实现类。
图三 jpdl
运行期活动实体对象关系图
上图是
jbpm4
在运行期的活动实例对象关系图,从图中我们可以看出,在运行期,
jbpm4
中定义了两个活动接口
Activity
和
ExternalActivity
,其中
ExternalActivity
继承自
Activity
。
Activity
是所有自动活动节点的父接口,其实现类为
JpdlActivity
,而
JpdlActivity
又衍生出了、
StartActivity
、
JoinActivity
、
ForkActivity
、
EndActivity
、
CreateTimerActivity
、
JavaActivity
、
EsbActivity
等实例活动对象。而
ExternalActivity
是具有等待状态的活动(
StateActivity
)父接口,像人工活动
TaskActivity
就是实现了此接口。
2、
核心引擎的调度算法
Jbpm3
的核心调度算法是基于
Token
机制的,在运行期这个
Token
在
Node Instance
之间流转,依靠
Token
的触发来推进流程。具体的调度机制,可参加胡长城的文章(
http://blog.csdn.net/james999/archive/2007/09/02/1769592.aspx
);其实这个
Token
来自于
Pertri-net
,感兴趣的读者可以去看
Pertri-net
中的
Token
及
Place
。
图四 jbpm3引擎调度图
Jbpm4
则去掉了
Token
,那么它的核心调度机制是怎样实现的呢?
图五 jbpm4流程启动序列图
图六 jbpm4 流程推进序列图
图五是在
jbpm4
中启动一个流程实例的执行序列图,图六是节点推进的执行序列图,从上面两个图中我们可以看到核心的调度是依据
Execution
的转移来实现的(
ExecutionImpl
可以是
ActivityExecution
、
ClientProcessInstance
、
EventListenerExecution
的实例),
Execution
实际上就是取代了
Jbpm3
中的
Token
,
Execution
的转移实际上就是根据状态机的变迁(
ActivityExecution
、
ClientProcessInstance
、
EventListenerExecution
实例之间的切换)加上调用相应的原子操作:
ExecuteNode
、
MoveToChildNode
、
MoveToParentNode
、
ProceedToDesitination
、
Signal
、
TakeTransition
(详见
pvm/internal/model/op
包下的相关类)来实现的。所以
Execution
实例的集合及有向图实际上就是运行期的路径。
3、
Event-Action
机制的变化
在
jbpm3
中是基于
Event-Action
机制来实现事件与动作的触发的,但是在
jbpm4
中则采用观察者模式来触发事件的。所有用户自己定义的动作,全部要实现
EventListener
接口,这些动作作为监听者(就是事件
Event
的观察者
Observer
)注册到相应的流程定义对象上(
ProcessElement
或者
Node
),而事件
Event
则作为被观察的对象(实际上就是
Observerable
),实际上在
jbpm4
中专门定义出了一个对象
ObservableElementImpl
,流程定义中的
NodeImpl
、
TransitionImpl
、
ProcessDefinitionImpl
均继承自此对象,因此这些元素本身就可以作为
Observerable
而被观察者来监控。
4、
客户端接口的变化
在
jbpm4
中对客户端的接口统一为
7
个服务接口:
ProcessService
、
ExecutionService
、
CommandService
、
TaskService
、
ManagementService
、
HistoryService
、
IdentityService
,这
7
个接口可以从
ProcessEngine
接口中获得,
jbpm4
在启动的过程中由
JbpmConfiguration
负责构建引擎。
Ø
ProcessService-
流程定义的服务接口,包括对流程定义的部署、查询、删除操作;
Ø
ExecutionService-
执行服务接口,包括启动流程、实例推进、设置变量等操作;
Ø
CommandService-Command
模式的服务接口,实际上就是将客户端的请求全部封装在一个调用接口中,然后由这个接口去调用
Command
接口的众多实现(
StartExecutionCmd
、
SignalCmd
、
SetVariablesCmd
、
GetTimersCmd
、
DeployCmd
、
NewTaskCmd
、
SubmitTask
、
ExecuteJobCmd
等等,具体可参加
pvm/internal/cmd
,
task/internal/cmd
包及其它包下实现
Command
接口的类),这是典型的
Command
模式的应用,感兴趣的读者可以去了解设计模式中的
Command
模式;
Ø
TaskService-
人工活动的服务接口,包括对任务的创建、提交、查询、保存、删除等操作;
Ø
ManagementService-web
管理控制台的服务接口,目前只有获得消息及计时器的接口实现;
Ø
HistoryService-
目前有对历史库中的流程实例、活动实例进行查询、某个流程定义中的所有活动的平均持续时间、某个流程定义中的某个活动实例的转移的执行次数
Ø
IdentityService-
用户、组、成员关系的相关操作方法
5、
历史库的加入
jBPM3
中数据库设计一直是我比较诟病的地方,尤其是其实例数据库没有设计历史库的概念并按照办结状态将运行结束的实例数据归入历史库,在这种情况下它的实例数据库就会随着时间而无限膨胀,这就阻碍了它的真实应用,而在
jBPM4
的最新代码中(注意
Alpha1
还没有出现),历史库的相关功能代码竟然出现了!详见
ExecutionImpl
最新代码中的
fireHistoryEvent
方法及一系列的
historyXXX
方法。在
ActivityBehaviour
的
execute
方法中加入了
historyTaskStart
方法的调用、
signal
方法中加入了
historyTaskEnd
方法的调用,而以上
2
个方法在
ExecutionImpl
中都是以历史事件(
HistoryEvent
有
4
个实现子类
ProcessInstanceStart
、
ProcessInstanceEnd
、
ActivityStart
、
ActivityEnd
分别用作流程实例的创建结束期、活动实例的创建结束期的历史数据处理)的触发机制来实现的,也就是在整个流程实例执行的过程中,都加入了对将运行数据存入历史库的历史事件(
HistoryEvent
)的触发。这样实例列表的查询可以只查询历史库。不过这里很遗憾的是,这个事件没有同时清除运行库的数据,这样还是会造成运行库的无限膨胀问题。