`
zwchen
  • 浏览: 785616 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

JBPM阶段性工作总结

阅读更多
快要离职了,工作交接期。但发现技术调研这种东西交接效率非常低啊。下面是自己写的一篇文档,算是做个备忘了。

一、工作概述
近一个月左右,对工作流,特别是开源工作流JBPM进行了一定的技术调研和尝试,现将工作总结一下。

我主要的工作时间花在以下几个方面,它们也是学习、研究工作流的一般途径:
1、JBPM3.2.1官方UserGuide(21章)通读了几遍,包括官方的examples、forum、wiki、apidoc。这五份资料来源是我认为最重要的。
2、google(english)、Javaeye和csdn相关工作流技术文章和评论,特别是“银狐999”的工作流blog。
3、国内OA、工作流、BPM产品的演示和功能介绍,如joinwork,思维加速,西安协同,摩卡等。
4、xflow、osworkflow、Willow、agileFlow等国内外开源工作流了解。
5、几本重要的工作流、BPM相关书籍和workflow模式,最重要的两本书是《OReilly Essential Business Process Modeling》、《MIT Press - Workflow Management--Models, Methods & Systems》。 另外JBPM的UserGuide第四章Graph Oriented Programming里有一个jbpm.gop.zip下载包,它就是JBPM引擎的mini版,几乎涵盖有JBPM引擎的绝大部分,如流转、分支、合并、、并行、同步、异步、事件、Action、表单。
6、JBPM的一个请假流程从页面到持久化的整个demo开发(约花两周时间),例子来源于csdn上一个非常典型的例子,有顺序、并发、互斥、条件分支等情形。另外,特别针对JBPM源码进行跟踪调试(四天)。
7、对当前项目的若干Use Case的深入分析,如流程图表示、流程实现。


二、JBPM环境和开发
JBPM开发环境JBPM我是从3.1.4版本开始研究的,但发现3.1.4版的designer在推荐的eclipse3.12下画流程图时,eclipse总是处理僵死状态,一个操作都要5s以上。无奈之下,下载JBPM3.2版本,该版本在eclipse3.1.2下designer无法正常使用。但在eclipse3.3,也就是官方刚出来的Europa版本下,其designer可以正常使用,但代码开发时,也是僵死状态,而在eclipse3.12下开发正常。所以,我现在的做法是,用JBPM的3.2.1版本,用eclipse的3.12做开发和调试,用eclipse3.3做流程可视化设计。另外,3.2.1对mail这类节点有支持。

JBPM控制台
JBPM的管理控制台从3.1.4到3.2.1有非常大的改进,如中文问题、界面、流程发布等。但在实际项目中,我们还是几乎无法使用,理由如下:
1、该管理控制台还是很粗糙,只有最基本的功能,没有权限、组织结构、细粒度的流程管理等功能,另外必须汉化。
2、其流程designer默认是生成JSF表单,也就是说整个管理控制台和流程开发最方便是JSF做表示层,这不符合我们当前的项目实际。另外,用自己的业务表,而不是JBPM自带的活表(数据库对应jbpm_variableinstance表),也就意味着JSF表单没法用上。
3、我们的流程存在大量中国特色的定制,如回退、临时流转、跳越,不可能将流程用JBPM的designer设计好,发布到控制台就ok这么简单。

当前,我们的项目需要流程控制台,但应该是完全自己开发,可以借鉴JBPM后台的设计实现思想,特别是流程查看时的流程图显示;另外我们还需要table格式的详细流转过程。
一般来说,控制台做得很强大的工作流系统,都是standalone方式运行,而不是我们现在的embeded方式。
关于JBPM控制台入门知识,JBPM官方wiki有非常详细的介绍。

JBPM的开发模式
实际的JBPM开发,我觉得应该注意以下几个问题:
1、业务处理的位置  我们知道,在MIS系统,如OA项目中引入工作流,主要是将流程逻辑和业务逻辑分开,流程数据持久化到流程引擎表,业务数据持久化到业务表。这就涉及到业务逻辑在哪里处理的问题。在JBPM中,是在ActionHandler还是在Business Service中?
ActionHandler中:我们将业务在JBPM的回调接口ActionHandler实现中处理,将业务表单对象通过ContextInstance的setTransientVariables()传入,在ActionHandler中持久化,也就是说,ActionHandler是我们的业务处理主体,可以通过在Task实例中记录业务表单ID。另外,数据库的Connection可以通过ActionHandler的ExecuteContext参数取得。
Business Service中:这个Service就对应于用Spring框架时的Service,我们可以在service方法里面调用JBPM的API,如JbpmConfiguration.getInstance().createJbpmContext(); TaskInstance ti = jContext.getTaskInstance(tiid); 将业务数据都持久化到JBPM的活表里,这样只在一个数据库Conntection上,可以避免分布式事务的问题。
上面两种方式,第一种是我推荐的,其基本思想是将工作流引擎当成一个集成框架,一切以流程为主线。第二种是将工作流引擎当成辅助的第三方库。两种方式对系统的侵入性都非常大,无侵入性我认为不现实。
参考:
[url]http://www.processdriven.org/process_liberation.html [/url]
[url]http://weblogs.java.net/blog/edgars/archive/2007/08/understanding_j_1.html [/url]

2、业务数据的存储 把业务数据持久化到JBPM的活表jbpm_variableinstance中,可以很容易地进行字段级别的权限控制,灵活的表单自定义,而且可以在JBPM的管理控制台上二次开发,将开发的工作量降到最低,而这是大多数商业工作流产品实现的目标。但是,活表对于实时的业务报表统计分析很低效,有时不可能,因为表单项是离散的,并且不是最重要的关注点。关注点可能是流程的执行效率统计,也就是流程数据统计。
成熟的工作流管理系统(工作流引擎只是其中一个组成部分)往往是一个任务或节点对应一个表单,这样很便于表单自定义,将流程设计、表单定义、权限控制、组织结构和任务分配一气呵成。我理解的表单,只是如同Struts里面的ActionForm,只是页面数据的收集和呈现形式,具体到这些表单怎么持久化,采用JBPM的活表或自定义的业务表均可,但我倾向后者。

3、面向流程的MIS系统的开发过程  对于一般的MIS系统开发,很强调领域分析、系统设计,也就是大量的UML图。这样的系统,往往可以抽象为增删改查CRUD,可以按页面分配工作量,增删改查都是无状态的,也就是说开发“增”并不影响“改”,一个操作一个业务,各业务操作互不影响、耦合。但有清晰流程的系统就不同,每一个业务操作都是有状态的,譬如一个OA的发文流程,可能有十来个步骤,各级领导审核、审批、查阅,每一步的操作都影响后面的业务流向,而且必须有各业务相关人员协作才能完成该发文目标,这样通过CRUD方式去理解这个系统就无法理清业务,如果通过流程驱动方式去建模,那么事情就简单了。
这样,就引发了一个问题:流程驱动的MIS系统,怎么制定软件开发过程?如果大家看过工作流产品(关键字:工作流、OA、协同、BPM)的demo介绍,就会知道,工作流系统的开发,往往和流程设计、表单设计打交道,在我们的成果物中(RUP中是artifact、工件),没有OO的概念,领域分析让位于流程分析:难道我们真的需要一个请假单LeaveForm的Domain?做报表系统开发,应该也没有强调Domain吧?因为它是数据驱动,没有强调业务层。
所以,我认为,流程驱动的业务系统开发,不要将概要设计、详细设计往上面套,它们的重点往往没有放在流程设计和实现这个根本问题上。也许,概要设计、详细设计这种瀑布开发过程挺适合低端的外包项目,譬如对日的外包,将低端Coding外包给中国公司。前提是,别人的详细设计可以确定95%以上需求,需求不明确带来的风险很小。另外,在用JBPM开发过程中,也许业务主要写在JBPM这个框架的ActionHandler回调接口中,我们详细设计的顺序图中的call或sendMessage,不适合反映这种过程,因为ActionHandler的lifecycle我们无法控制。那么详细设计的意义何在?
那么,软件过程怎么定?我认为还是敏捷一点,只关注三点:用户需求(详细的用例文档和原型)、流程设计、流程实现。文档只集中在第一点。
我认为,参考基于成熟的商业工作流产品开发模式,就是我们系统的开发的模式。

三、JBPM对常见流程问题的解决
JBPM的API文档非常匮乏,但是,JBPM的源码内部有很多注释,其代码可读性非常强,核心代码我认为不超过1w行,引擎核心代码也许只有两三千行。另外,阅读源码,最好对UML活动图、Petri网、Workflow模式较熟悉,譬如Join. setDiscriminator(),如果不了解Workflow模式的Discriminator模式,该方法就不知所措。
Process本质上,只有两个对象:Node和Transition(节点和有向弧),只要这两类对象就可以完整绘出一个流程图,当然,Node有很多子类,譬如Start、End、Fork、Join、Decision等。
JBPM的过程调度,是通过Token在流程节点之间转移实现的。譬如TaskInstance.end()的时候,调用Token.signal(),在signal()内部,依次调用:Node.leave(),Transition.take(),Node.enter(),这三个调用依次引发如下三个event:node-leave,transition,node-enter,在event内部,就处理我们自定义的ActionHandler和记日志。从中我们可以看出,事件(event)处理和Token调度是分离的。上面的三个event是重复循环的,可以驱动流程向前进行:离开当前节点过渡进入下一节点。
上面就是JBPM的大致调度过程,清晰、简洁。
参考:
JBPM引擎架构:http://blog.csdn.net/james999/archive/2007/09/02/1769592.aspx
JBPM微型架构实现:http://docs.jboss.com/jbpm/gop/jbpm.gop.zip

下面我对JBPM对工作流中常见问题的解决方案总结一下,基本上都来源于网络,自己试验了一下,很可行。
1、互斥任务
譬如,员工请假流程中,员工请假申请提交后,系统应该创建两个并发任务:员工取消和主管审批,只要任何一个任务结束,另外一个就应该结束。
一种实现方式是,在请假申请Node后Fork出两个Node,员工取消和主管审批,它们Transition 的ActionHandler里结束另外一个Node的TaskInstance。
另外一种实现方式是,在一个Node里创建上面两个Task,在Node节点里设置属性signal="first" end-tasks="true"。signal="first"指一个任务结束,当前节点就流转;end-tasks="true"指结束该节点时自动结束其它没有完成的任务。
参考:http://jbpm.group.iteye.com/group/blog/59741

2、动态创建任务,会签或任务分派
像会签这类动态创建任务的情形,用流程图很难描述,所以一般是通过代码手工创建,JBPM为这提供了很方便的接口。
JBPM的实现方式。在task-node设置create-tasks="false",在该task-node的event-enter事件中,自定义ActionHandler,处理任务创建的工作。
说明:对JBPM的API用得得心应手,必须对其API设计实现、引擎思想有较深入理解,譬如Event机制、Token调度、Workflow模式等,其API绝对没有Servlet API那么简单,容易上手。
参考:http://www.cnblogs.com/amushen/archive/2007/07/03/804237.aspx

3、循环节点,文件传阅
在默认的JBPM的designer里无法画出指向自身的有向弧,可以先在该节点的XML流程定义文件里写出指向自身的Transition,这样在图形显示下就会出现指向自身的有向弧。当然,重复创建两个类似的节点,之间有往返有向弧也可以实现。

4、并发子流程JBPM自身对子流程的支持不够灵活,如只能创建一个子流程(ProcessState.setSubProcessDefinition()而不是addSubProcessDefinition())
一种解决方案是用流程的Hierarchy分级结构方式,请参考:http://jeffreyhsu.iteye.com/blog/29917

...............
...............

5、客户的Visio流程原型实现的探讨
该流程原型,要求把JBPM的流程定义模块重新实现,有一定难度。但我认为,实现是完全可以的,但初步实现需要一个多人月的时间(以自己目前的能力)。
作为我个人的角度,我觉得Leader应该给开发人员充分的授权,信任开发人员,时间自由支配,定一个大致milestone就可以了。前段时间的技术调研太浮躁,一天一个方向,根本就没有调研深度。做一件事情需要多少时间就是多少时间,人为主观去控制,注定会失败的。
如果现在想按客户的要求实现,技术比以前的预想难多了,因为现在的流程定义是活的,相当于我们做了一个流程管理控制台和流程设计器。可以做,但风险大,不过,静下心来,是完全可以完成的,因为JBPM这部分相关代码只有几千行(千万不要忘了,JBPM只是一个naked流程引擎,不是工作流管理系统)。项目现在面临的一个问题是,前期开发有一个时间瓶颈,核心代码没有开发出来,后面的开发无法进行,以当前的管理模式,势必会让前期开发人员浮躁(自由的思想才会有深度,有创造力)。

客户原型实现看法:
流程定义和修改:JBPM有JpdlXmlReader,负责XML流程定义解析的,把该类和其关联类弄明白就差不多了,估计约两天时间,我花完整一天时间读过,不太难。
节点编辑,出口编辑:解析过程同上,
数据项编辑:利用JBPM自己的活表(TaskController相关),实现不是很难。

如果按客户的方式做,做成功了,其它项目就很好复用,因为它就是做了一个通用的元框架,也算是拿做产品的要求来做项目。

另外,如果不做成通用框架,解决现在项目中的若干技术问题难度都不大,如回退、串并行、版本控制、自由流、多子流程、强制跳转、自定义时限、权限控制、流程监控。但“提供自定义流程功能”,就是上面客户的要求,这个难度很大,和中棉项目自定义报表难度有的一拼(中棉项目自定义报表以失败告终)。

就总结到这儿吧,Workflow、BPM是企业软件的趋势,以后还得努力啊!






  • shipping.rar (642.1 KB)
  • 描述: 这个例子是完整可运行的。请把webwork、spring、hibernate和jbpm的所有jar包放入web-inf的lib下。然后将这个rar包下的jbpm3.2.1的sql导入mysql中。大家可以用src里面的两个XXXTest测试用例跑一下,代码很粗糙,需要大量重构,请见谅。只是作为了解jbpm的例子还是不错。这个例子也是网上的,只是我敲了一遍,并且加了jsp界面。 注意,那个请假流程的并发实现在业务逻辑上是有问题的:员工取消流程和请假审批流程应该是互斥的,后来没来得及改进了。
  • 下载次数: 2204
分享到:
评论
12 楼 mengpb 2012-10-18  
11 楼 suerzxt 2008-09-10  
非常有收获,谢谢.
10 楼 chenbo_soft 2008-04-14  
今天刚刚看见这篇文章,希望得到帮助啊
9 楼 spiritfrog 2008-04-07  
拜读了你的文章, 豁然开朗,示例程序不错,不过指出一下,web上跑应该用leavle1或者leavel3。
另外:员工取消流程和请假审批流程应该是互斥的,后来没来得及改进了
确实有问题,其中一个任务结束另外的还在,一开始没有看清楚介绍,迷惑了半天。
8 楼 cenjun615 2008-02-26  
感触良深
7 楼 fire01312 2007-11-28  
楼主 看了你的文章感觉你对jbpm已经比较精通了 ,现在我的项目也要使用jbpm了,以后多向你请教了奥
6 楼 mad_sea 2007-10-22  
好文章!
5 楼 huagongfang 2007-09-30  
Jbpm流程名\节点名可以定义为中文吗??
中文名好象在数据库中存放的是乱码,这个问题如何解决??????
4 楼 zwchen 2007-09-26  
   你提出的问题,主要是jbpm的process definition没有deploy,你将我写的某个Test用例“shipping\src\main\com\hisoft\shipping\leave\test”下的LeaveProcessTest.testDeployProcessDefinition()方法,在eclipse里面run一下就ok了(通过右键的junit快捷键)。如果部署成功,就说明你的DB连接配置都是成功了。以后就可以顺利测试了。
   你问的问题,都是最基本的java工程、jbpm概念导致的,请先整体把握这个。
   我那个例子是没有啥问题的,因为我工作交接时,好几个人都拿去用过。你需要配置的,仅仅是加上所有相关jar,以及config下的hibernate.cfg.xml的DB连接信息。
  Good Luck!
3 楼 geniegao 2007-09-26  
程序可以运行了。但是提交请假申请就出错。
org.jbpm.JbpmException: can't create a process instance when processDefinition is null
org.jbpm.graph.exe.ProcessInstance.<init>(ProcessInstance.java:128)
org.jbpm.graph.exe.ProcessInstance.<init>(ProcessInstance.java:92)
org.jbpm.JbpmContext.newProcessInstance(JbpmContext.java:409)
com.hisoft.shipping.service.LeaveService.writeLeave(LeaveService.java:36)
com.hisoft.shipping.web.action.LeaveFormAction.submitDraft(LeaveFormAction.java:113)
com.hisoft.shipping.web.action.LeaveFormAction.execute(LeaveFormAction.java:59)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)......
这个工程是不是缺少一些文件啊?
您不是说是“完整可运行的”?我调了好几天了,为什么还是不能用啊?我很着急,请您帮忙,谢谢。
2 楼 geniegao 2007-09-24  
请问我将工程导入以后,buildpath中找不到
org.eclipse.jst.j2ee.internal.web.container和
org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v5.5
怎么办啊?
谢谢!
1 楼 Bluesnails 2007-09-17  
获益匪浅,谢谢!

相关推荐

Global site tag (gtag.js) - Google Analytics