JBPM源码浅析

JBPM源码浅析
JBPM源码浅析

JBPM源码浅析

关键字: jbpm workflow 工作流

离职啦,工作交接中,记录一下。

就如同了解Servlet规范、Servlet容器设计和实现一样,学会一种workflow 的建模、引擎设计和实现也是必备的。工作流这东西是业务系统的一个核心模块,现在的大多数企业业务系统大多数是业务驱动的,如新闻行业采编发、制造业的采供销、金融保险的审批等,协同OA就不用说了。BPM、ESB、SOA现在很火啊!

下面的总结肯定欠成熟,70%合理就不错啦,看到这篇blog的朋友,一定要批判接受哦。

当前我指的JBPM是3.2版本,因为从JBPM2.0到3.0,其API从package到class 都完全重新设计了,以及其背后的建模思想和架构。在2.0版本里,是按照Spring+Hibernate那种Transaction Script方式组织的,OO的概念比较弱,里面是大量的interface、impl、service。而3.0版本,完全按Domain Model方式组织,Hibernate透明持久化,它是我见到的O/R Mapping最优雅的应用。

在当前的3.2版本里,其整体架构可以这么去理解:领域对象,如ProcessDefinition、ProcessInstance、Node、Token、Transition等,都是Rich Model,里面的方法主要是处理业务,以及建立领域对象之间的关联,持久化则完全放在XXXSession中,如TaskMgmtSession,GraphSession等,也可以认为这些XXXSession是DAO,负责处理持久化。另外,

org.jbpm.persistence.db.DbPersistenceService这些类相当于最底层的数据库Helper类。总之,JBPM的技术架构非常清晰易懂,也是非常典型的Domain Driven Design,在这种架构中,分层的概念被弱化了。

上面是从架构的角度看待JBPM设计,其引擎设计和实现,则隐藏在架构下。了解其引擎设计思想,我的建议是,先仔细读读JBPM的User Guide第四章Graph Oriented Programming,专门探讨流程建模的理论,里面附带了一个微型的JBPM 实现,几乎包括流程建模的绝大部分,如顺序流、并行、分支等:

https://www.360docs.net/doc/d217206169.html,/jbpm/gop/jbpm.gop.zip,我建议研读JBPM源码前,先把这个理解透,JBPM的流程引擎核心代码和它非常相似,包括类名,只是扩展了一些。

我用代码统计工具统计了一下,JBPM源码总共4w多行,除去注释和空行,约2万6千行。需要我们hack的核心、比较难、代码多的类约40个(共400多),反正它花了我整四天的时间,现在基本都弄清楚了。我主要是通过一个请假流程的部署、创建、任务执行来动态debug、静态查看的。JBPM源码中最难读懂的那部分是引擎调度,也就是org.jbpm.graph相关的几个包,最重要的是GraphElement和其子类Transition等、Node及其子类Fork等、ExecuteContext 和Token。而引擎调度这部分, JBPM附带了一个微型JBPM实现,我在前面介绍

过。除了引擎调度,其它相关源码就非常简单了。

在JBPM中,有很多API是供JBPM自身调用的,如流程定义文件中支持的Expression语言,脚本等(org.jbpm.jpdl.el.impl),我们不用理会。

我们主要和下面三类API打交道:

JBPM环境的配置、service的管理、流程的部署和卸载:它主要体现在org.jbpm 中,另外辅助包有org.jbpm.jpdl.xml、org.jbpm.configuration。

org.jbpm.configuration负责services对象的创建,相当于一个微型的IoC容器、对象工厂,负责services的生命周期管理,如加载、创建、调用和销毁,像Job调度服务、数据库持久化服务、异步消息服务等。需要说明的是,由于其package下的ObjectFactoryImpl也是一个IoC容器,和Spring的IoC容器是有相同的职责:对象的管理。所以在这种松耦合架构下,可以将JBPM和Spring 集成,如业务系统和JBPM引擎的事务处理、对象管理、配置管理等。请参考Spring-Module开源项目。

org.jbpm.jpdl.xml负责流程定义文件的解析,譬如XML文件的解析,相关领域对象的实例化。通过hack其源码和原理,我们可以在业务系统中自定义流程,让用户可以自己定义、变更流程。

JBPM中领域对象:如Node、Token、ProcessInstance、TaskInstance等,它们有三个职责,一个是保持从DB中加载流程和任务相关的数据或将数据持久化到DB。第二,为各领域对象建立关联,方便实现透明持久化(复杂的领域关联在Hibernate的mapping文件里配置)。第三,就是处理业务规则,如引擎调度算法,但不负责持久化。

JBPM中持久化领域对象的Manager,DAO:如TaskMgmtSession。它们主要是持久化领域对象,如session.save(ProcessInstance);或是执行查询,如根据流程ID查询该流程实例,查询操作都是配置在hibernate mapping中的hql语句,如hibernate.queries.hbm.xml。但可能并不能满足我们的要求,譬如按时间段查询当前的流程实例,任务的分页查询,这样,就需要我们自己扩展这些DAO 类。由于它们查询是只读操作,所以很容易,而且扩展几乎是必然了,因为要是按JBPM默认的,把所有的Result查询出来,再过滤,性能是个很大的问题,我们应该按需查询。

--------------------------------------

下面按功能分类说明一下:

JBPM流程的部署和卸载

JBPM流程的部署和卸载,无论是通过管理控制台还是自定义部署,最终都是通过JbpmContext的 deployProcessDefinition(ProcessDefinition)部署,而ProcessDefintion实例的创建,是通过调用ProcessDefinition的相关方法,如parseXmlResource (String xml)。

ProcessDefintion实例的创建,有多种输入源,譬如XML字符串、XML文件、zip

包,还有最抽象的Reader、InputStream。如果在用户的业务系统里面自定义发布业务流程,也最终是调用ProcessDefinition相关方法。但流程定义解析,最核心的只有一个类:org.jbpm.jpdl.xml包下的JpdlXmlReader,

org.jbpm.JbpmContext:该类可以理解为Fa?ade模式的实现,与流程相关的manager类可以通过它取得,如getGraphSession()、getServices(),它是获取其它服务的快捷方式,也算是一个delegate类。如果大家对Context的概念比较敏感,其类职责就很好理解,在Servlet容器里面也有ServletContext的概念,和它意思差不多。对一般的系统软件一般来说,Context往往建模成Container的上下文。在JBPM中,它还负责流程部署、加载、卸载。

JBPM的任务管理

JBPM和任务管理相关的类主要是org.jbpm.taskmgmt.def和

org.jbpm.taskmgmt.exe,像任务创建、分配等。

和任务相关的最重要的有两个方面,一个是任务分配,另一个是和任务相关的表单。当然,任务查询和任务日志也很重要。

任务分配:解决的是将任务分配给谁,它有静态分配和动态分配两种,前者是在流程定义文件里部署,后者是通过代码动态指定。它涉及到的概念有Actor,PooledActor,Swimlane,AssignmentHandler。在做demo时,譬如JBPM官方自带的例子webSale里,就是通过Expression静态部署任务角色的,如user(leo),group(orderManager),但它用到了JBPM的第三方组件Identity,其实通过Expression静态分配角色,本质上也是通过AssignmentHandler实现的,如ExpressionAssignmentHandler。

任务分配,一般比较灵活的方案是在流程的Swimlane里面部署自定义action,然后重用swimlane。另外一种方案是,在每个task里面部署AssignmentHandler 实现类。

任务相关表单:主要是org.jbpm.taskmgmt.def.TaskController,它是task scope下的表单字段,类似Servlet里面的HttpServletRequest的

setAttribute()。如果是process scope下的表单项,是

org.jbpm.context.exe.ContextInstance,类似于Servlet里面的HttpSession 的setAttribute()。

附带说一下任务查询,所有有关查询和持久化的操作,都集中在包org.jbpm.db 中,如任务相关的TaskMgmtSession,要是这些find方法不满足业务要求,建议自己扩展。

JBPM的流程日志

JBPM的流程日志,主要是记录一些事件(Event),如流程创建、任务分配,它们在GraphElement的fireEvent时,譬如在Node.leave()(Token离开当前节点时)触发fireEvent事件(在该事件方法里执行自定义Action),同时记录日志。我们关心的日志主要有process、task、transition、signal四类,每个下面还有事件细分,如task创建和分配。通过日志,我们统计流程执行效率,

也可以得到详细的流程步骤日志。

日志的查询,请参考LoggingSession及其相关类。顺便说一下,所有的日志类都继承于ProcessLog,约20来个。JBPM已经声明的日志查询方法,可能并不能满足我们的要求,自行扩展吧。

其它API

JBPM API里有org.jbpm.web、org.jbpm.security等,前者负责在web容器启动时加载JBPM引擎,将当前Session的用户设置为任务的Actor等,后者负责安全相关的认证和授权。源码很简单,不多说了。我建议实现类似业务需求时,不妨参考其实现,但拿来用就会发现它太简陋了。

研究jBPM已有一段时间了,今天终于决定拿点东西出来,但请大家原谅不能分享源码。之所以拿出来,希望通过交流认识到更多技术一线的同志们,结点人缘。本人不才只念完了高中,求职路屡战屡败,只好踏实地弄点东西出来撑下门面,希望有所帮助,找到一份满意的工作。

大多研究JBPM的,对其引擎的扩展开发都不曾苦恼,但提及其可视化设计工具都希望能有一款WEB版设计器。

苦恼过后,便有了开发设计器的冲动。首先通过网上找到的WEB 流程设计工具,多半是非流程研究人员的产品,拿来用要经过大量的修改,不太可取,也不容易修改,参考倒是有些价值,在此谢过;另外由于刚学会了JavaScript在页面实现的拖曳功能。鉴于此便开始了行动,现在想想还有些大胆。由于一直没抽出时间来,拖了两个多月,终于写下了这篇文章。

基于javaScript+css+vml的jBPM web designer,由于使用了vml 只支持IE浏览器(IE5+),其中没有使用任何javaScript开发框架,但模仿了extJs框架的css界面风格。开发过程中参考了extJs、prototype、jQuery等javaScript开发框架;参考了jBPM designer eclipse 插件;参考了shine Workflow Designer截图、以及圈子中shappy1978贴出来的截图(当时还回帖希望这位大哥分享源码,结果失望,也就狠下心来独干,造自己的轮子);还参考了webflow、XiorkFlow、EMSFlow(applet)等,XiorkFlow是早期看过的流程设计工具。在此谢过以上提供的参考。

以下以贴图方式介绍jBPM3 web designer。

1、流程设计器主界面,采用纯JS且面向对象的编程方式(事件处理机制swing、extjs思想中毒很深)开发,动态生成div等HTML代码,利用外部样式表以实现多风格支持,根据窗口大小自适应宽高,以使编辑区域最大可视化,仿jBPM designer eclipse 插件布局与操作习惯(其中个人觉得属性输入要比eclipse 插件方便些),仿extJs框架的css界面风格。主界面分为三部分,工具栏、编辑区、属性栏,支持鼠标拖动设定大小及最大化、最小化、还原功能。编辑区支持网格显示。

目前设计器支持开始、结束、分支、合并、决策、任务、邮件7种节点(可以容易扩展新节点)并可以通过鼠标拖曳操作编辑大小,流程转换可以通过鼠标操作支持直线及折线。节点的连接操作进行验证,如只允许拖入一个开始节点;开始节点只允许单个from连接;结束节点只允许to连接,但支持多个连接;两个节点只能有唯一的同向连接等等。点击编辑区的空白处在属性栏显示流程定义的属性配置,点击节点则在属性栏显示节点的属性配置,点击流程转换或其label同样在属性栏显示其属性配置。在属性栏输入配置信息将自动保存并响应到图形展示上(如输入节点名称,则编辑区中节点显示的文字相应地改变)。整个设计器工作过程相当流畅。所有的配置信息将生成符合JPDL规范的XML 流程定义文件。由于最终的产物是XML字符串,这赋予了流程设计器不仅仅能够定义出符合jBPM3的定义文件,稍做修改同样能定义出符合

jPBM4,以及其它任何的基本XML的定义文件。

2、图形编辑,节点及流程转换,利用vml标签获得良好的视觉效果(考虑兼容其它浏览器,可以开发基于svg、canvas或纯js的图形模型)。

网格

节点选中(节点选中后,可以通过鼠标按下拖动节点,改节点显示位置,也可以通过键w、a、s、d或up、left、dowm、rigth来移动节点,选中的节点能够通过delete键进行删除,连同其所有的form及to转换

将一起被删除。当两个节点重叠时,选中节点始终显示于最上面)

相关主题
相关文档
最新文档