这篇指南描述了一种为了使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中使用刚刚定义的DbPersistenceServiceimport 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.