在研究JBPM,要应用到项目开发之中,由于系统使用spring作为业务层管理,而JBPM默认使用的hibernate作为持久层管理。我需要将它们集成在一起,幸运的是spring与hibernate本身就有完全兼容的集成应用方案,但是之中还是遇到不少问题。
我这使用的JBPM版本是3.1.2,下载的包是jbpm-starters-kit-3.1.2.zip。
首先要将JBPM持久层部分通过系统自动持久化(使用内存数据库hsqldb除外)。我们先将JBPM部署持久层需要的jar包摘出来,虽然JBPM应用需要不少jar包,但是部署持久层并不是需要很多,清单如下:
jar包 |
路径(BaseDir = jbpm-starters-kit-3.1.2) |
说明 |
hibernate3 |
BaseDir \jbpm\lib\hibernate\ |
hibernate核心程序,版本3.1 |
spring |
需要下载 |
Spring核心程序,这里使用的版本是2.0 |
jbpm-3.1.2 |
BaseDir \jbpm\build\ |
JBPM核心程序 |
dom4j-1.6.1 |
BaseDir \jbpm\lib\dom4j\ |
支持解析xml核心程序 |
spring-modules-jbpm31 |
需要下载 |
spring与jbpm集成支持包 |
jboss-j2ee |
BaseDir \jbpm\lib\jboss\ |
JBOSS支持JBPM需要的java程序 |
cglib-2.1_2jboss |
BaseDir \jbpm\lib\jboss\ |
支持JOSS-J2EE和hibernate.tool.hbm2ddl,如果不使用会报错: java.lang.NoClassDefFoundError: net/sf/cglib/proxy/CallbackFilter
|
bsh |
BaseDir \jbpm\lib\jboss\ |
支持JOSS-J2EE,如果不使用会报错:bsh/EvalError |
asm |
BaseDir \jbpm\lib\jboss\ |
支持JOSS-J2EE,如果不使用会报错: org/objectweb/asm/Type |
antlr-2.7.5H3 |
BaseDir \jbpm\lib\jboss\ |
支持JOSS-J2EE,如果不使用会报错: antlr/ANTLRException |
ehcache-1.1 |
BaseDir \jbpm\lib\hibernate\ |
如果使用hibernate缓存则需要 |
ehcache-1.1 |
BaseDir \jbpm\lib\hibernate\ |
如果使用hibernate缓存则需要 |
除了上面的jar之外,还需要支持数据库的一些jar包。下面还需要JBPM提供的一些XML配置文件,具体清单如下:
文件名
|
路径
|
说明
|
default.jbpm.cfg.xml
|
jbpm-3.1.2,jar\org\jbpm\
|
jbpm主配置文件
|
ehcache.xml
|
BaseDir \jbpm\src\config.files\
|
如果使用hibernate缓存则需要配置
|
hibernate.cfg.xml
|
BaseDir \jbpm\src\config.files\
|
???,后面具体说明
|
下面可以开始spring的配置了,要让系统自动持久化JBPM持久层,我们得先连上数据库,在spring中我们使用org.apache.commons.dbcp.BasicDataSource类作为数据源连接(需要commons-dbcp.jar支持)。例如:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:oracle"></property>
... 省略若干
</bean>
然后我们使用spring集成hibernate来建立数据库会话工厂SessionFactory
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource" />
</property>
<property name="mappingLocations">
<value>classpath*:org/jbpm/**/*.hbm.xml</value>
</property>
</bean>
接下来我们要配置的就是JBPM比较关键的BEAN,即jbpmConfiguration;
<bean id="jbpmConfiguration" class="org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean">
<property name="configuration" value="classpath:default.jbpm.cfg.xml" />
</bean>
配置其实很简单,只要将主配置xml文件放在src目录下,按照上面配置就可以,那么问题出来了,如何让它自动部署呢?
JBPM本身提供jbpmConfiguration.createSchema方法来实现,而可以通过硬编码方式,或者在IOC配置jbpmConfiguration中加入〈property name="createSchema" value="true" /〉实现;
我们使用第一种方式看看效果;我这里已经做好了一个监听ServletContextListener,实现方法如下:
public void contextInitialized(ServletContextEvent sce) {
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
JbpmConfiguration jbpmConfiguration = (JbpmConfiguration)ctx.getBean("jbpmConfiguration");
try{
jbpmConfiguration.createSchema();
}catch(Exception e) {
e.printStackTrace();
}
}
最终控制台输出为:org.hibernate.HibernateException: hibernate.cfg.xml not found,缺少这个配置文件;看来这种方式启动,这个文件是不可缺了;那么我们在src添上这个文件再运行看看效果;
第二次控制台输出为:org.hibernate.HibernateException: The dialect was not set. Set the property hibernate.dialect. 这是怎么回事?
从网上我也找到很多关于这样的配置,例如网上配置如下:
<bean id="jbpmConfiguration" class="org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean">
<property name="configuration" value="classpath:default.jbpm.cfg.xml" />
<property name="sessionFactory" ref="sessionFactory" />
<property nname="createSchema" value="true" />
</bean>
如果按照建立单独数据源dataSource,还是会出现这样的错误,除非使用hibernate.cfg.xml配置数据源;那么我们要使用单独的数据源部署应该怎么做?
由于是 jbpmConfiguration.createSchema();方法报出的错误,我们先将错误详细信息打印出来:
org.hibernate.HibernateException: The dialect was not set. Set the property hibernate.dialect.
at org.hibernate.dialect.Dialect.getDialect(Dialect.java:607)
at org.hibernate.dialect.Dialect.getDialect(Dialect.java:629)
at org.hibernate.tool.hbm2ddl.SchemaExport.<init>(SchemaExport.java:89)
at org.hibernate.tool.hbm2ddl.SchemaExport.<init>(SchemaExport.java:64)
at org.jbpm.persistence.db.DbPersistenceServiceFactory.getSchemaExport(DbPersistenceServiceFactory.java:76)
at org.jbpm.persistence.db.DbPersistenceServiceFactory.createSchema(DbPersistenceServiceFactory.java:107)
at org.jbpm.JbpmConfiguration.createSchema(JbpmConfiguration.java:415)
看见在调用createSchema方法时,在方法体调用getSchemaExport方法中有段代码:
public synchronized SchemaExport getSchemaExport() {
if (schemaExport==null) {
log.debug("creating schema export");
schemaExport = new SchemaExport(getConfiguration());
}
return schemaExport;
}
可以看见创建初始化SchemaExport对象,我们先看创建这个对象的参数getConfiguration()方法:
public synchronized Configuration getConfiguration() {
if (configuration==null) {
String hibernateCfgXmlResource = null;
if (JbpmConfiguration.Configs.hasObject("resource.hibernate.cfg.xml")) { // 如果配置里含有resource.hibernate.cfg.xml项,那么读这个配置对应的文件
hibernateCfgXmlResource = JbpmConfiguration.Configs.getString("resource.hibernate.cfg.xml");
}
......省略若干
configuration = HibernateHelper.createConfiguration(hibernateCfgXmlResource, hibernatePropertiesResource);
}
return configuration;
}
这里说读resource.hibernate.cfg.xml里的配置,我们可以打开JbpmConfiguration的配置文件default.jbpm.cfg.xml,看到确实是有这个配置,那么注释掉行吗?答案是不行的,最后在createConfiguration方法里还是会默认加载classpath:hibernate.cfg.xml,这是hibernate默认规定的,如果这个文件也没有,则就报错hibernate.cfg.xml not found;
那么就是说这里初始化SchemaExport对象的环境变量就必须是从hibernate.cfg.xml这里配置的,对应到org.hibernate.tool.hbm2ddl.SchemaExport.89行方法调用getDialect方法出错;我们跟进到源码看见getDialect方法是这么写的:
public static Dialect getDialect() throws HibernateException {
String dialectName = Environment.getProperties().getProperty( Environment.DIALECT );
if ( dialectName == null ) throw new HibernateException( "The dialect was not set. Set the property hibernate.dialect." );
....
}
意思是从环境变量属性中获取DIALECT 属性名称dialectName如果是空,则报错。
看来我误会了JBPM例子的意思,使用JbpmConfiguration.createSchema方法的方式创建表结构要求是指定hibernate配置(也就是必须要在hibernate.cfg.xml里指定hibernate.properties配置信息),如果不配置hibernate-properties那么必然会出现这样缺少环境变量或缺少数据源信息的错误;
如果是这样,那么解决这个问题?我们要先知道我们的目的是什么?
就是将hibernate配置的持久层配置信息持久化到指定的数据库。那么JbpmConfiguration.createSchema
方法是不是自由JOSS-JBPM独有的呢?我们还是看源码分析,还是从这个方法入口进去,看见persistenceServiceFactory.createSchema();方法,继续跟进,发现getSchemaExport()方法,而这个方法是关键,即也是错误at org.jbpm.persistence.db.DbPersistenceServiceFactory.createSchema中指定的位置。好的这下我们可以再跟进发现一段代码schemaExport = new SchemaExport(getConfiguration());是它才能够调用create创建脚本方法,而SchemaExport并不是JBPM自身有的。
这好像有些废话,用过hibernate的都知道hibernate本身就有Create-Schema功能,源码在org.hibernate.tool.hbm2ddl包下,配置属性为:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource" />
</property>
<property name="mappingLocations">
<value>classpath*:org/jbpm/**/*.hbm.xml</value>
</property>
<property name="hibernateProperties">
<props><prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
好的为了不再说废话hibernate.hbm2ddl.auto,大家可以自己查阅资料。再次部署测试......等待......终于创建成功了。但是还有个问题是hibernate.hbm2ddl.auto-create是在什么时候创建的呢?它是为什么能成功,而jbpmConfiguration.createSchema()不行?
那我们依然看源码,既然是配在LocalSessionFactoryBean类下,就从这里看起。先思考,持久化肯定是在连接数据源,并生成会话之后才能够创建持久模型阿,又从源码上看这个类除了基本的set、get方法外,就只剩afterPropertiesSet中的buildSessionFactory。在此方法里我们可以发现一条代码:
if (this.hibernateProperties != null) {
// Add given Hibernate properties to Configuration.
config.addProperties(this.hibernateProperties);
}
即添加hibernate配置属性,这就对应了IOC里配置的hibernateProperties项,再看最后的newSessionFactory方法中:
Environment.verifyProperties( properties ); //在这里环境变量已经被注入进来了
Properties copy = new Properties();
copy.putAll( properties );
PropertiesHelper.resolvePlaceHolders( copy );
Settings settings = buildSettings( copy ); // 而最后将hibernateProperties配置,转化为对应的settings类
return new SessionFactoryImpl(
this,
mapping,
settings,
getInitializedEventListeners()
);
跟进SessionFactoryImpl构造函数,发现在295行中有这么段代码:
if ( settings.isAutoCreateSchema() ) new SchemaExport(cfg, settings).create(false, true); 这不就是自动持久化的判断吗?终于真像大白了,我们再总结下这个问题:
1,采用JBPMConfiguration.createSchema方法,在初始化SchemaExport时用到的环境变量必须是从hibernate.cfg.xml来的,而这个文件如果不指定全hibernate信息,则会报错。
2,如果让createSchema是在创建SessionFactory时,所用到的环境变量可以是从IOC容器里配置的,所以甚至可以不使用hibernate.cfg.xml文件。
有些口水话.....
分享到:
相关推荐
jbpm4.3与spring整合的一个小文档
近期网上有人介绍jBPM4与Spring整合的2种方式,但没有人贴出代码,闲着无聊写了个例子,源码见附件,在WEBLOGIC下运行正常,事务由spring控制http://ip:7001/Spring/helloWorld.do
风中叶老师讲的JBPM4与Spring整合例子代码 JBPM4 Spring OA工作流系统
在spring3中整合jbpm5的例子,前台用spring mvc3做了简单的页面。 其中用到了jbpm5的persistence,local human service等,简单、完整。 用的mysql数据库,修改下spring datasource的配置,然后用mvn jetty:run编译...
JBPM4.4+spring+ext整合
JBPM4.3与Spring会签 实例,欢迎交流ningjinlin@gmail.com
NULL 博文链接:https://1960370817.iteye.com/blog/2392653
spring+hibernate+jbpm详细整合文档
jbpm4.4 ibatis-spring 整合
T1 spring-IOCjQueryt1.Jbpm设计t2.流程持久化t3整合spring
经典的jbpm5整合例子,自动简表。只要保证数据库打开就可以了。运行简单,附带详细的使用说明。是jbpm学习开发则的必背资源。
jbpm5.4 spring mvc 集成开发 Jetty maven JTA 事务等配置!
spring+jbpm的配置示例,jbpm配置,希望大家一起进行学习,共同提高
jbpm与spring集成开发指南,描述了jbpm与spring开发过程。
jbpm4.4整合spring2.5(ibatis与hibernate全整合)
jbpm spring驱动,这个驱动用于jbpm集成spring情况。
发现很难找到一个合适的,能跑的起来的,整合ssh的例子,之前在csdn上花费不少分下了好多个,能跑起来的好像就1个,不是jar包不匹配就是些其他的莫名奇妙的错误,对应刚刚接触jbpm的人来说,一下子完全解决不了,...
spring3.2+jBPM6整合实例
jbpm4.0实例(整合spring2.5+ext3.0+hibernate)
1-版本以及系统配置jbpm版本3.2.3...jBPM默认使用的是内存数据库hsqldb|---deploy用来部署你的应用的包和资源|---designer这里是Eclipse插件,这样你就可以在图形界面来定义你的业务流程|---