Spring+Mysql+Jbpm整合
关键字: jbpm前言
最近因为工作需要做一个工作流相关的DEMO,研究了一下JBPM,记录一下个人的心得与体会。
软件环境:
- spring2.0.2
- hibernate3.2.2
- spring modules 0.8 (Jbpm3.1)
- jbpm3.1.4
- struts2.0.6
配置
Spring Module Jbpm模块提供了几个工具类用来整合spring和jbpm,关于具体的配置可以参见spring module下载包中的参考手册,按照上面的指示来就OK了,这里粘贴示例配置。
- xml version="1.0" encoding="UTF-8"?>
- >
- <beans default-autowire="byName" default-lazy-init="true">
- <bean id="approveWorkflow"
- class="org.springmodules.workflow.jbpm31.definition.ProcessDefinitionFactoryBean">
- <property name="definitionLocation"
- value="classpath:jbpm/audit/processdefinition.xml" />
- bean>
- <bean id="jbpmConfiguration"
- class="org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean">
- <property name="sessionFactory" ref="sessionFactory" />
- <property name="configuration" value="classpath:jbpm/jbpm.cfg.xml" />
- <property name="processDefinitions">
- <list>
- <ref local="approveWorkflow" />
- list>
- property>
- bean>
- <bean id="jbpmTemplate"
- class="org.springmodules.workflow.jbpm31.JbpmTemplate">
- <constructor-arg index="0" ref="jbpmConfiguration" />
- <constructor-arg index="1" ref="approveWorkflow" />
- bean>
- beans>
比较关键的是为了能够使JBPM实体和业务实体使用同一个会话工厂,这样可以在JBPM流程实例中持久化业务实体对象。必须将业务实体映射和JBPM的实体映射进行整合。我的作法是改写JBPM本身提供的hibernate.cfg.xml文件,将业务实体包括在里面。
- xml version='1.0' encoding='utf-8'?>
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
- <hibernate-configuration>
- <session-factory>
- <property name="hibernate.cache.use_second_level_cache">
- false
- property>
- <property name="hibernate.cache.use_query_cache">
- false
- property>
- <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialectproperty>
- <property name="hibernate.show_sql">falseproperty>
- <property name="hibernate.query.factory_class">
- org.hibernate.hql.ast.ASTQueryTranslatorFactory
- property>
- <mapping resource="com/emap/jbpm/model/Apply.hbm.xml"/>
- <mapping resource="org/jbpm/graph/action/Script.hbm.xml"/>
- <mapping resource="org/jbpm/db/hibernate.queries.hbm.xml" />
- <mapping resource="org/jbpm/graph/def/ProcessDefinition.hbm.xml"/>
- <mapping resource="org/jbpm/graph/def/Node.hbm.xml"/>
- <mapping resource="org/jbpm/graph/def/Transition.hbm.xml"/>
- <mapping resource="org/jbpm/graph/def/Event.hbm.xml"/>
- <mapping resource="org/jbpm/graph/def/Action.hbm.xml"/>
- <mapping resource="org/jbpm/graph/def/SuperState.hbm.xml"/>
- <mapping resource="org/jbpm/graph/def/ExceptionHandler.hbm.xml"/>
- <mapping resource="org/jbpm/instantiation/Delegation.hbm.xml"/>
- ........
- session-factory>
- hibernate-configuration>
下面我们看看sessionFactory工厂的配置。
- xml version="1.0" encoding="UTF-8"?>
- >
- <beans default-autowire="byName" default-lazy-init="true">
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
- <property name="driverClassName" value="${jdbc.driverClassName}"/>
- <property name="url" value="${jdbc.url}"/>
- <property name="username" value="${jdbc.username}"/>
- <property name="password" value="${jdbc.password}"/>
- bean>
- <bean id="sessionFactory"
- class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
- <property name="dataSource" ref="dataSource" />
- <property name="configLocations">
- <list>
- <value>classpath:jbpm/hibernate.cfg.xmlvalue>
- list>
- property>
- bean>
- <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
- <property name="sessionFactory" ref="sessionFactory"/>
- bean>
- beans>
遗留问题
如何使用JBPM Process Designer插件?
一直没找到如何使用JBPM Process Designer插件的使用文档,比如如何配置JBPM安装路径,如何部署。目前唯一用到的功能就是编写流程文件。
如何发布流程文件?
对于如何发布流程文件,我比较同意如下帖子中的观点,编程实现或许是最简洁的方式。
www.pcdog.com/edu/java/2006/11/v171946.html
如何关联业务实体和流程实例?
JBPM主要用来管理业务流程,记录每个流程进入哪个环节,同时还要保存一些状态,这些状态信息可能来自于业务实体。JBPM的实现方式是将这些状态信息序列化到数据库的表列。
假定有一个订单处理的流程,现在要获取某个角色当前的所有任务列表,同时将关联的订单信息展示给用户,我们应该如何处理?目前我想到有以下几种方式:
方式一:在构建任务实例的时候,将业务实体持久化到contextInstance,在获取任务列表时从任务实例中直接解析出业务实体。如果需要保存的业务实体数据量很大,这会给JBPM数据库造成很大的数据冗余。
方式二:在构建任务实例的时候,仅将业务实体的唯一标识符持久到contextInstance,在获取任务列表时从任务实例中解析出任务实体的唯一标识符,然后再根据此标识符查询业务实体数据库。这种情况会造成查询一个包含N个的任务列表时,需要N+1次数据库查询,显然性能是无法满足需求的。
方式三:是否可以在构建业务实体时,和TaskInstance进行关联?这种方式会造成业务实体和JBPM紧耦合,而且必须对JBPM本身有比较深刻的理解。
有什么更好的办法解决这种问题呢?个人以为方式一可能是目前性价比最好的解决方式吧。
一点体会
JBPM看来在国内并没有得到很多的应用,资料都比较稀缺,唯一的参考手册也是非常的浅显和简单。而其源码的注释不是很好,这在国外的开源软件中是很罕见的。
JBPM提供的某些API不是很全,举个例子,假定我要查询某个角色某个时间段的所有任务列表。因为TaskMgmtSession仅提供了findXXXTaskInstances(String actorId)方法,所以我只能先查询出该角色的所有任务列表,采用如下代码:
- TaskMgmtSession taskMgmtSession = context.getTaskMgmtSession();
- List tasks = taskMgmtSession.findPooledTaskInstances(actorId);
然后再在内存中使用类似如下代码进行过滤。
- if (task.getName().equals(taskName) && !task.hasEnded())
这种方式太笨拙和低效了。
评论
JBPM提供的某些API不是很全,举个例子,假定我要查询某个角色某个时间段的所有任务列表。因为TaskMgmtSession仅提供了findXXXTaskInstances(String actorId)方法,所以我只能先查询出该角色的所有任务列表,采用如下代码:
java 代码
1. TaskMgmtSession taskMgmtSession = context.getTaskMgmtSession();
2. List tasks = taskMgmtSession.findPooledTaskInstances(actorId);
然后再在内存中使用类似如下代码进行过滤。
java 代码
1. if (task.getName().equals(taskName) && !task.hasEnded())
这种方式太笨拙和低效了。
你可以看一下它是怎么查的,无非是使用hibernate的NamedQuery查询数据库,你可以在他的基础上添加一下过滤条件,而不用每次都查询所有的记录然后在过滤。在数据量大的时候全取出来性能是有问题的。
这个问题是因为你上述两段代码的作用只是删除了流程定义表中的记录,比如流程实例中的记录并没有得到删除,所以如果要使测试对数据没有破坏,最彻底的办法只能是每次启动前创建SCHEMA,停止时卸载SCHEMA。
你说的是扩展JBPM的业务实体呢,还是在业务表中保留一些流程相关的信息?业务表中应该保留哪些相关信息,这个尺度的把握可能比较重要。
安装插件很EASY,我不知道在Eclipse的Preference里JBOSS JBPM选项是如何设置,以及这个设置是用来做什么的?我目前只用他来画流程图。
JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
//由 processdefinition.xml 生成相对应的流程定义类 ProcessDefinition
InputStream is = new FileInputStream(
"D:/oa/workflow/processes/PresaleHandlerForBusinessReport.xml");
ProcessDefinition processDefinition = ProcessDefinition.parseXmlInputStream(is);
try {
jbpmContext.deployProcessDefinition(processDefinition);
} catch (Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
如果是卸载流程定义文件的话:
JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
jbpmContext.getGraphSession().deleteProcessDefinition(Long.parseLong("5"));
} catch (Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
记得jbpmContext一定要关闭。这里有个问题,假如你要删除的那个流程被使用的过的话,当你再去卸载这个流程的时候,这个流程未必能删除的了。 我有的时候会碰到这样的情况。
发表评论
- 浏览: 85216 次
- 性别:

- 来自: 北京

- 详细资料
搜索本博客
链接
最新评论
-
[翻译] FreeMarker快速上 ...
我先转载了,留得日后看, 谢谢!
-- by qingfeng825 -
[翻译] FreeMarker快速上 ...
very good,思路明晰,条理清楚。 本来想自己整理一篇,但是楼主已经把我要 ...
-- by qingfeng825 -
[翻译] JBoss 4.0.5 应用 ...
-- by sdasdasda -
[翻译] YUI 事件处理机制
-- by shimch -
Spring+Mysql+Jbpm整合
LZ,我想问一下你有没有遇见过HIBERNATE在处理BOOLEAN类型时转化的 ...
-- by leyen






评论排行榜