jBPM3 vs jBPM4

JBoss Goup目前已经发布了jBPM4 Alpha1版本,在版本4中最大的变化就是引入PVM(流程虚拟机)的概念,而引擎内部的调度算法中重要的Token机制,在新版中也去掉了,纵观整个代码,变化可以说非常的大,笔者接下来就试着来比较一下这种变化,让大家能有个直观的认识。当然Jbpm4JBoss的官方网站上的Road map中,在今年的71号才会发布第一个正式版本,因此后续可能还会有变化。

1、  流程定义对象的变化:

Jbpm3流程定义对象关系图:

 图一 jbpm3流程定义对象关系图

从上图我们可以看出这jbpm3中,GraphElement是流程图中所有流程元素的父对象,而整个流程是由ProcessDefinitionNodeTransition三个主要对象构成;

 

      Jbpm4pvm实体对象关系图:

 图二 PVM实体对象关系图

从上图可以看出,由于PVM概念的引入,所以在jbpm3中的Graph包在jbpm4中被移除了。在pvm中,在设计期,所有节点元素的父类为ProcessElementImpl,流程的主要组成元素NodelmplTransitionImplProcessDefinitionImplEventImpl则都直接或间接继承自ProcessElementImpl。在运行期:jbpm4把流程的运行期行为定义为执行行为(ExecutionImpl)及原子操作行为(AtomicOperation,其具体实现为ExecuteNodeProceedToDestinationTakeTranstionMoveToParentNodeMoveToChildNodesignal),其中ExecutionImpl是流程实例、活动实例、事件监听器的所有执行期行为的实现类。

 

图三 jpdl运行期活动实体对象关系图

 上图是jbpm4在运行期的活动实例对象关系图,从图中我们可以看出,在运行期,jbpm4中定义了两个活动接口ActivityExternalActivity,其中ExternalActivity继承自ActivityActivity是所有自动活动节点的父接口,其实现类为JpdlActivity,而JpdlActivity又衍生出了、StartActivityJoinActivityForkActivityEndActivityCreateTimerActivityJavaActivityEsbActivity等实例活动对象。而ExternalActivity是具有等待状态的活动(StateActivity)父接口,像人工活动TaskActivity就是实现了此接口。

 2、  核心引擎的调度算法

Jbpm3的核心调度算法是基于Token机制的,在运行期这个TokenNode Instance之间流转,依靠Token的触发来推进流程。具体的调度机制,可参加胡长城的文章(http://blog.csdn.net/james999/archive/2007/09/02/1769592.aspx);其实这个Token来自于Pertri-net,感兴趣的读者可以去看Pertri-net中的TokenPlace

 

图四 jbpm3引擎调度图

Jbpm4则去掉了Token,那么它的核心调度机制是怎样实现的呢?

 

图五 jbpm4流程启动序列图

 

图六 jbpm4 流程推进序列图

图五是在jbpm4中启动一个流程实例的执行序列图,图六是节点推进的执行序列图,从上面两个图中我们可以看到核心的调度是依据Execution的转移来实现的(ExecutionImpl可以是ActivityExecutionClientProcessInstanceEventListenerExecution的实例),Execution实际上就是取代了Jbpm3中的TokenExecution的转移实际上就是根据状态机的变迁(ActivityExecutionClientProcessInstanceEventListenerExecution实例之间的切换)加上调用相应的原子操作:ExecuteNodeMoveToChildNodeMoveToParentNodeProceedToDesitinationSignalTakeTransition(详见pvm/internal/model/op包下的相关类)来实现的。所以Execution实例的集合及有向图实际上就是运行期的路径。

 3、  Event-Action机制的变化

jbpm3中是基于Event-Action机制来实现事件与动作的触发的,但是在jbpm4中则采用观察者模式来触发事件的。所有用户自己定义的动作,全部要实现EventListener接口,这些动作作为监听者(就是事件Event的观察者Observer)注册到相应的流程定义对象上(ProcessElement或者Node),而事件Event则作为被观察的对象(实际上就是Observerable),实际上在jbpm4中专门定义出了一个对象ObservableElementImpl,流程定义中的NodeImplTransitionImplProcessDefinitionImpl均继承自此对象,因此这些元素本身就可以作为Observerable而被观察者来监控。

4、  客户端接口的变化

jbpm4中对客户端的接口统一为7个服务接口:ProcessServiceExecutionServiceCommandService TaskService ManagementServiceHistoryServiceIdentityService,这7个接口可以从ProcessEngine接口中获得,jbpm4在启动的过程中由JbpmConfiguration负责构建引擎。

Ø  ProcessService-流程定义的服务接口,包括对流程定义的部署、查询、删除操作;

Ø  ExecutionService-执行服务接口,包括启动流程、实例推进、设置变量等操作;

Ø  CommandService-Command模式的服务接口,实际上就是将客户端的请求全部封装在一个调用接口中,然后由这个接口去调用Command接口的众多实现(StartExecutionCmdSignalCmdSetVariablesCmdGetTimersCmdDeployCmdNewTaskCmdSubmitTaskExecuteJobCmd等等,具体可参加pvm/internal/cmdtask/internal/cmd包及其它包下实现Command接口的类),这是典型的Command模式的应用,感兴趣的读者可以去了解设计模式中的Command模式;

Ø  TaskService-人工活动的服务接口,包括对任务的创建、提交、查询、保存、删除等操作;

Ø  ManagementService-web管理控制台的服务接口,目前只有获得消息及计时器的接口实现;

Ø  HistoryService-目前有对历史库中的流程实例、活动实例进行查询、某个流程定义中的所有活动的平均持续时间、某个流程定义中的某个活动实例的转移的执行次数

Ø  IdentityService-用户、组、成员关系的相关操作方法

 

5、历史库的加入

jBPM3中数据库设计一直是我比较诟病的地方,尤其是其实例数据库没有设计历史库的概念并按照办结状态将运行结束的实例数据归入历史库,在这种情况下它的实例数据库就会随着时间而无限膨胀,这就阻碍了它的真实应用,而在jBPM4的最新代码中(注意Alpha1还没有出现),历史库的相关功能代码竟然出现了!详见ExecutionImpl最新代码中的fireHistoryEvent方法及一系列的historyXXX方法。在ActivityBehaviourexecute方法中加入了historyTaskStart方法的调用、signal方法中加入了historyTaskEnd方法的调用,而以上2个方法在ExecutionImpl中都是以历史事件(HistoryEvent有4个实现子类ProcessInstanceStart、ProcessInstanceEnd、ActivityStart、ActivityEnd分别用作流程实例的创建结束期、活动实例的创建结束期的历史数据处理)的触发机制来实现的,也就是在整个流程实例执行的过程中,都加入了对将运行数据存入历史库的历史事件(HistoryEvent)的触发。这样实例列表的查询可以只查询历史库。不过这里很遗憾的是,这个事件没有同时清除运行库的数据,这样还是会造成运行库的无限膨胀问题。

 

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐