您的位置:首页 > 编程语言 > Java开发

Spring+Mysql+Jbpm整合(转)

2007-08-13 09:28 330 查看
最近因为工作需要做一个工作流相关的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 代码

1. <!--sp-->xml version="1.0" encoding="UTF-8"?>
2. <!--CTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"</sp-->>
3. <beans default-autowire="byName" default-lazy-init="true">
4. <bean id="approveWorkflow"
5. class="org.springmodules.workflow.jbpm31.definition.ProcessDefinitionFactoryBean">
6. <property name="definitionLocation"
7. value="classpath:jbpm/audit/processdefinition.xml" />
8. bean>
9. <bean id="jbpmConfiguration"
10. class="org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean">
11. <property name="sessionFactory" ref="sessionFactory" />
12. <property name="configuration" value="classpath:jbpm/jbpm.cfg.xml" />
13. <property name="processDefinitions">
14. <list>
15. <ref local="approveWorkflow" />
16. list>
17. property>
18.
19. bean>
20. <bean id="jbpmTemplate"
21. class="org.springmodules.workflow.jbpm31.JbpmTemplate">
22. <constructor-arg index="0" ref="jbpmConfiguration" />
23. <constructor-arg index="1" ref="approveWorkflow" />
24. bean>
25. beans>
26.

比较关键的是为了能够使JBPM实体和业务实体使用同一个会话工厂,这样可以在JBPM流程实例中持久化业务实体对象。必须将业务实体映射和JBPM的实体映射进行整合。我的作法是改写JBPM本身提供的hibernate.cfg.xml文件,将业务实体包括在里面。
xml 代码

1. <!--sp-->xml version='1.0' encoding='utf-8'?>
2.
3. <!--CTYPE hibernate-configuration PUBLIC </sp-->
4. "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
5. "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
6.
7. <hibernate-configuration>
8. <session-factory>
9.
10. <property name="hibernate.cache.use_second_level_cache">
11. false
12. property>
13. <property name="hibernate.cache.use_query_cache">
14. false
15. property>
16. <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialectproperty>
17. <property name="hibernate.show_sql">falseproperty>
18. <property name="hibernate.query.factory_class">
19. org.hibernate.hql.ast.ASTQueryTranslatorFactory
20. property>
21.
22.
23. <!-- 下面是业务实体映射 -->
24. <mapping resource="com/emap/jbpm/model/Apply.hbm.xml"/>
25.
26. <!-- 下面是JBPM引擎本身的实体映射 -->
27. <mapping resource="org/jbpm/graph/action/Script.hbm.xml"/>
28.
29. <mapping resource="org/jbpm/db/hibernate.queries.hbm.xml" />
30.
31. <!-- graph.def mapping files -->
32. <mapping resource="org/jbpm/graph/def/ProcessDefinition.hbm.xml"/>
33. <mapping resource="org/jbpm/graph/def/Node.hbm.xml"/>
34. <mapping resource="org/jbpm/graph/def/Transition.hbm.xml"/>
35. <mapping resource="org/jbpm/graph/def/Event.hbm.xml"/>
36. <mapping resource="org/jbpm/graph/def/Action.hbm.xml"/>
37. <mapping resource="org/jbpm/graph/def/SuperState.hbm.xml"/>
38. <mapping resource="org/jbpm/graph/def/ExceptionHandler.hbm.xml"/>
39. <mapping resource="org/jbpm/instantiation/Delegation.hbm.xml"/>
40.
41. ........
42.
43. session-factory>
44. hibernate-configuration>

下面我们看看sessionFactory工厂的配置。
xml 代码

1. <!--sp-->xml version="1.0" encoding="UTF-8"?>
2. <!--CTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"</sp-->>
3. <beans default-autowire="byName" default-lazy-init="true">
4.
5. <!-- 数据源定义,使用Apache DBCP 连接池 -->
6. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
7. <property name="driverClassName" value="${jdbc.driverClassName}"/>
8. <property name="url" value="${jdbc.url}"/>
9. <property name="username" value="${jdbc.username}"/>
10. <property name="password" value="${jdbc.password}"/>
11. bean>
12.
13. <!-- Hibernate SessionFactory -->
14. <bean id="sessionFactory"
15. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
16. <property name="dataSource" ref="dataSource" />
17. <property name="configLocations">
18. <list>
19. <value>classpath:jbpm/hibernate.cfg.xmlvalue>
20. list>
21. property>
22. bean>
23. <!--Hibernate TransactionManager-->
24. <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
25. <property name="sessionFactory" ref="sessionFactory"/>
26. bean>
27. 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)方法,所以我只能先查询出该角色的所有任务列表,采用如下代码:
java 代码

1. TaskMgmtSession taskMgmtSession = context.getTaskMgmtSession();
2. List tasks = taskMgmtSession.findPooledTaskInstances(actorId);

然后再在内存中使用类似如下代码进行过滤。
java 代码

1. if (task.getName().equals(taskName) && !task.hasEnded())

这种方式太笨拙和低效了。

如果是发布流程到数据库的话:

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一定要关闭。这里有个问题,假如你要删除的那个流程被使用的过的话,当你再去卸载这个流程的时候,这个流程未必能删除的了。 我有的时候会碰到这样的情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: