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); } } }