shared sessionfactory between JBPM + Spring in SEAM
spotlight2001 Nov 30, 2008 10:27 AMmy goal: i wanted my appl tables separated from jbpm tables. so i have two DBs. Two sessionfactories. One for my app. The other for JBPM. I want the JBPM-sessionfactory spring-wired, so i can use it in other spring beans.
I saw several options:
1) let JBPM create its sessionfactory and somehow use it then as spring bean
2) create spring bean sessionfactory and make sure JBPM uses it
3) use sessionFactoryJndiName
in jbpm-config.
Does anyone know how to use option 3)? I sounds like the least work.
I choose option 2). Disadvantages:
-) on startup: spring must start BEFORE seam - which isnot recommend by docs
???why?
howto:
1) Listener: obtain servlet context (I need it to create spring beans) (how to do this better?)
2) 08/15 spring config and create a sessionfactory
3) subclass JBPM - DbPersistenceServiceFactory (this is a lazy init sessionfactory holder).
1) obtain servlet context
public class JbpmUtilStartupListener implements ServletContextListener {
private static ServletContext servletContext;
public static ServletContext getServletContext() {
return servletContext;
}
public void contextDestroyed(ServletContextEvent event) {
//do nothing
}
public void contextInitialized(ServletContextEvent event) {
servletContext = event.getServletContext();
}
}2) spring config: (unlike seam docu with components.xml which gave me errors)
web.xml
<!-- WARN: seam docu says: put SEAM BEFORE SPRING i have spring here to initialize a sessionfactory which i later user for jbpm --> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <listener> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class> </listener> <listener> <listener-class>at.iqsoft.jbpm.spring.JbpmUtilStartupListener</listener-class> </listener> <listener> <listener-class>org.jboss.seam.servlet.SeamListener</listener-class> </listener>
application context (spring config):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
<context:annotation-config/>
<jee:jndi-lookup id="jbpmDataSource" jndi-name="java:comp/env/jdbc/jbpm"/>
<bean id="jbpmSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="jbpmDataSource"/>
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
<property name="hibernateProperties">
<value>
<!-- override jbpm default values - like datasource
hibernate.dialect=${hibernate.dialect}
hibernate.query.substitutions=true 'Y', false 'N'
hibernate.cache.use_second_level_cache=true
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
-->
hibernate.hbm2ddl.auto=validate
</value>
<!-- Turn batching off for better error messages under PostgreSQL -->
<!-- hibernate.jdbc.batch_size=0 -->
</property>
</bean>
<bean id="seamSessionFactory" class="org.jboss.seam.ioc.spring.SeamManagedSessionFactoryBean">
<property name="sessionName" value="hibernateSession"/>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<constructor-arg ref="seamSessionFactory"/>
</bean>
</beans>subclass of JBPM sessionfactory holder
package at.iqsoft.jbpm.spring;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.SessionFactory;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.persistence.db.DbPersistenceServiceFactory;
import org.jbpm.svc.Services;
import org.springframework.util.Assert;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* use this if you want that JBPM + SPRING use the SAME SESSIONFACTORY
*
* this g*/
public class SharedSessionFactoryUtilListener implements ServletContextListener {
private static final Log log = LogFactory.getLog(SharedSessionFactoryUtilListener.class);
public void contextDestroyed(ServletContextEvent event) {
//do nothing
}
public void contextInitialized(ServletContextEvent event) {
ServletContext servlet = event.getServletContext();
WebApplicationContext spring = WebApplicationContextUtils.getRequiredWebApplicationContext(servlet);
String sessionFactorySpringId;
{
sessionFactorySpringId = servlet.getInitParameter("wm.sharedSSF.id"); //
if (sessionFactorySpringId != null) {
//user decided to customize session factory spring bean id
} else{
//use default param
sessionFactorySpringId = "sessionFactory";
}
}
Object sessionFactoryObj = spring.getBean(sessionFactorySpringId);
Assert.notNull(sessionFactoryObj, "no sessionfactory");
SessionFactory sessionFactory = (SessionFactory) sessionFactoryObj; //XXX classcaste
//retrieve jbpm
{
JbpmConfiguration config = JbpmConfiguration.getInstance();
JbpmContext jbpm = config.getCurrentJbpmContext();
if (jbpm == null) {
jbpm = config.createJbpmContext();
}
Services services = jbpm.getServices();
DbPersistenceServiceFactory persistenceServiceFactory =
(DbPersistenceServiceFactory) services
.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
persistenceServiceFactory.setSessionFactory(sessionFactory);
}
}
}