这篇指南描述了一种为了使Spring和jBPM(当然还有Seam)能使用同一个Hibernate SessionFactory而将Seam,Spring和jBPM集成的方法。
首先您要确保使用的是2.1.0版本的Seam,因为2.0.1版本的Seam和SpringTransaction会有些麻烦。
相关的配置部分如下:
1.在你的Spring bean配置中,像平常一样定义你的Hibernate SessionFactory并且设置如下这些属性
<
bean
id
="hibernateSessionFactory"
class
="
"
>
<!-- The hibernate properties -->
< property name ="hibernateProperties" >
< props >
< prop key ="hibernate.hbm2ddl.auto" > update </ prop >
<!-- set to create-drop to NOT maintain state between two executions of the app -->
< prop key ="hibernate.transaction.flush_before_completion" >
true
</ prop >
< prop key ="hibernate.connection.release_mode" >
after_transaction
</ prop >
</ props >
</ property >
<!-- this property must be set to false so we can use independent sessions -->
< property name ="useTransactionAwareDataSource" >
< value > false </ value >
</ property >
< property name ="mappingResources" >
< list >
<!-- here you have to list all the *hbm.xml files for jBPM -->
<!-- see the default hibernate.cfg.xml file from jBPM -->
</ bean >
2.为了集成Seam和Spring,我们需要两个bean
<!-- The hibernate properties -->
< property name ="hibernateProperties" >
< props >
< prop key ="hibernate.hbm2ddl.auto" > update </ prop >
<!-- set to create-drop to NOT maintain state between two executions of the app -->
< prop key ="hibernate.transaction.flush_before_completion" >
true
</ prop >
< prop key ="hibernate.connection.release_mode" >
after_transaction
</ prop >
</ props >
</ property >
<!-- this property must be set to false so we can use independent sessions -->
< property name ="useTransactionAwareDataSource" >
< value > false </ value >
</ property >
< property name ="mappingResources" >
< list >
<!-- here you have to list all the *hbm.xml files for jBPM -->
<!-- see the default hibernate.cfg.xml file from jBPM -->
</ bean >
<
bean
id
="sessionFactory"
class ="org.jboss.seam.ioc.spring.SeamManagedSessionFactoryBean" >
< property name ="sessionName" value ="hibernateSession" />
</ bean >
< bean id ="localTransactionManager"
class ="org.springframework.orm.hibernate3.HibernateTransactionManager" >
< property name ="sessionFactory" ref ="hibernateSessionFactory" />
</ bean >
以上就是针对Spring的配置
class ="org.jboss.seam.ioc.spring.SeamManagedSessionFactoryBean" >
< property name ="sessionName" value ="hibernateSession" />
</ bean >
< bean id ="localTransactionManager"
class ="org.springframework.orm.hibernate3.HibernateTransactionManager" >
< property name ="sessionFactory" ref ="hibernateSessionFactory" />
</ bean >
现在我们需要配置components.xml文件
<!--
use the power of Spring transactions
-->
< spring:spring-transaction platform-transaction-manager-name ="localTransactionManager" />
< persistence:managed-hibernate-session name ="hibernateSession" auto-create ="true"
session-factory ="#{hibernateSessionFactory}" />
< component class ="org.jboss.seam.bpm.Jbpm" >
< property name ="processDefinitions" > processdefinition.jpdl.xml </ property >
</ component >
为了在jBPM中使用hibernateSession,我从jBPM中扩展了一个子类DbPersistenceService:
< spring:spring-transaction platform-transaction-manager-name ="localTransactionManager" />
< persistence:managed-hibernate-session name ="hibernateSession" auto-create ="true"
session-factory ="#{hibernateSessionFactory}" />
< component class ="org.jboss.seam.bpm.Jbpm" >
< property name ="processDefinitions" > processdefinition.jpdl.xml </ property >
</ component >
package
your.namespace.jbpm.integration;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.jboss.seam.Component;
import org.jboss.seam.contexts.Contexts;
import org.jbpm.svc.Service;
/**
* @author Frank Bitzer
*
* EL4J - The Extension Library for Java.
*
*/
public class DbPersistenceServiceFactory extends
org.jbpm.persistence.db.DbPersistenceServiceFactory {
private static final long serialVersionUID = 997L ;
SessionFactory sessionFactory;
/**
* { @inheritDoc }
*/
public Service openService() {
// create instance of own service implementation
return new your.namespace.jbpm.integration.DbPersistenceService( this );
}
/**
* Retrieve Hibernate sessionFactory
*/
@Override
public synchronized SessionFactory getSessionFactory() {
if (sessionFactory == null ) {
if (Contexts.isApplicationContextActive()){
// access seam component holding session
Session session = (Session)
Component.getInstance( " hibernateSession " );
// and extract sessionFactory
sessionFactory = session.getSessionFactory();
}
}
return sessionFactory;
}
/**
* Set sessionFactory
*/
@Override
public void setSessionFactory(SessionFactory sessionFactory) {
this .sessionFactory = sessionFactory;
}
}
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.jboss.seam.Component;
import org.jboss.seam.contexts.Contexts;
import org.jbpm.svc.Service;
/**
* @author Frank Bitzer
*
* EL4J - The Extension Library for Java.
*
*/
public class DbPersistenceServiceFactory extends
org.jbpm.persistence.db.DbPersistenceServiceFactory {
private static final long serialVersionUID = 997L ;
SessionFactory sessionFactory;
/**
* { @inheritDoc }
*/
public Service openService() {
// create instance of own service implementation
return new your.namespace.jbpm.integration.DbPersistenceService( this );
}
/**
* Retrieve Hibernate sessionFactory
*/
@Override
public synchronized SessionFactory getSessionFactory() {
if (sessionFactory == null ) {
if (Contexts.isApplicationContextActive()){
// access seam component holding session
Session session = (Session)
Component.getInstance( " hibernateSession " );
// and extract sessionFactory
sessionFactory = session.getSessionFactory();
}
}
return sessionFactory;
}
/**
* Set sessionFactory
*/
@Override
public void setSessionFactory(SessionFactory sessionFactory) {
this .sessionFactory = sessionFactory;
}
}
package
your.namespace.jbpm.integration;
import org.hibernate.Session;
import org.jbpm.JbpmContext;
import org.jbpm.persistence.db.DbPersistenceServiceFactory;
import org.jbpm.svc.Services;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
/**
* @author Frank Bitzer
*
* EL4J - The Extension Library for Java.
*
*/
public class DbPersistenceService extends
org.jbpm.persistence.db.DbPersistenceService {
private static final long serialVersionUID = 996L ;
public DbPersistenceService(
DbPersistenceServiceFactory persistenceServiceFactory) {
this (persistenceServiceFactory, getCurrentServices());
}
static Services getCurrentServices() {
Services services = null ;
JbpmContext currentJbpmContext = JbpmContext.getCurrentJbpmContext();
if (currentJbpmContext != null ) {
services = currentJbpmContext.getServices();
}
return services;
}
DbPersistenceService(DbPersistenceServiceFactory persistenceServiceFactory,
Services services) {
super (persistenceServiceFactory);
this .persistenceServiceFactory = persistenceServiceFactory;
this .isTransactionEnabled = persistenceServiceFactory
.isTransactionEnabled();
this .isCurrentSessionEnabled = persistenceServiceFactory
.isCurrentSessionEnabled();
this .services = services;
}
/**
* Use Hibernate sessionFactory to retrieve a Session instance.
*/
public Session getSession() {
if ((session == null ) && (getSessionFactory() != null )) {
session = getSessionFactory().openSession();
mustSessionBeClosed = true ;
mustSessionBeFlushed = true ;
mustConnectionBeClosed = false ;
isTransactionEnabled = ! SessionFactoryUtils.isSessionTransactional(
session, getSessionFactory());
if (isTransactionEnabled) {
beginTransaction();
}
}
return session;
}
}
为了结束工作,只需要像下面一样简单的在jbpm.cfg.xml中使用刚刚定义的DbPersistenceService
import org.hibernate.Session;
import org.jbpm.JbpmContext;
import org.jbpm.persistence.db.DbPersistenceServiceFactory;
import org.jbpm.svc.Services;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
/**
* @author Frank Bitzer
*
* EL4J - The Extension Library for Java.
*
*/
public class DbPersistenceService extends
org.jbpm.persistence.db.DbPersistenceService {
private static final long serialVersionUID = 996L ;
public DbPersistenceService(
DbPersistenceServiceFactory persistenceServiceFactory) {
this (persistenceServiceFactory, getCurrentServices());
}
static Services getCurrentServices() {
Services services = null ;
JbpmContext currentJbpmContext = JbpmContext.getCurrentJbpmContext();
if (currentJbpmContext != null ) {
services = currentJbpmContext.getServices();
}
return services;
}
DbPersistenceService(DbPersistenceServiceFactory persistenceServiceFactory,
Services services) {
super (persistenceServiceFactory);
this .persistenceServiceFactory = persistenceServiceFactory;
this .isTransactionEnabled = persistenceServiceFactory
.isTransactionEnabled();
this .isCurrentSessionEnabled = persistenceServiceFactory
.isCurrentSessionEnabled();
this .services = services;
}
/**
* Use Hibernate sessionFactory to retrieve a Session instance.
*/
public Session getSession() {
if ((session == null ) && (getSessionFactory() != null )) {
session = getSessionFactory().openSession();
mustSessionBeClosed = true ;
mustSessionBeFlushed = true ;
mustConnectionBeClosed = false ;
isTransactionEnabled = ! SessionFactoryUtils.isSessionTransactional(
session, getSessionFactory());
if (isTransactionEnabled) {
beginTransaction();
}
}
return session;
}
}
< jbpm-context >
< service name ="persistence" >
< factory >
< bean class ="your.namespace.jbpm.integration.DbPersistenceServiceFactory" >
< field name ="isTransactionEnabled" >
< false />
</ field >
</ bean >
</ factory >
</ service >
</ jbpm-context >
Also make sure your Spring WebApplicationContext is initialized before the startup of Seam. This can be achieved by placing the org.jboss.seam.servlet.SeamListener behind the listener for Spring in your web.xml.