2 Replies Latest reply on Nov 30, 2008 11:17 AM by spotlight2001

    shared sessionfactory between JBPM + Spring in SEAM

    spotlight2001

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


        • 1. Re: shared sessionfactory between JBPM + Spring in SEAM
          spotlight2001

          !!!WARN: the last class in my last post is the wrong one. This is creepy - i cant find an edit button. I would admire an edit button (at least if no other posts are around). ... it was an earlier try which failed. heres the jbpm session factory holder:



          package at.iqsoft.jbpm.spring;
          
          import javax.servlet.ServletContext;
          
          import org.apache.commons.logging.Log;
          import org.apache.commons.logging.LogFactory;
          import org.hibernate.SessionFactory;
          import org.jbpm.persistence.db.DbPersistenceServiceFactory;
          import org.jbpm.util.JndiUtil;
          import org.springframework.util.Assert;
          import org.springframework.web.context.WebApplicationContext;
          import org.springframework.web.context.support.WebApplicationContextUtils;
          
          public class SharedDbPersistenceServiceFactory extends
          DbPersistenceServiceFactory {
               private static final long serialVersionUID = 9093607503357425464L;
               private static Log log = LogFactory.getLog(DbPersistenceServiceFactory.class); 
               SessionFactory sessionFactory;
          
               @Override
               public synchronized SessionFactory getSessionFactory() {
                    if (sessionFactory==null) {
                         final String sessionFactoryJndiName = getSessionFactoryJndiName();
                         if (sessionFactoryJndiName!=null) {
                              log.debug("looking up hibernate session factory in jndi '"+sessionFactoryJndiName+"'");
                              sessionFactory = (SessionFactory) JndiUtil.lookup(sessionFactoryJndiName, SessionFactory.class);
                         } else {
                              log.debug("building hibernate session factory");                    
                              ServletContext servlet = JbpmUtilStartupListener.getServletContext();
                              //get from spring
                              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");
                              this.sessionFactory = (SessionFactory) sessionFactoryObj; //XXX classcaste
                         }
                    }
                    return sessionFactory;
               }
          }
          


          • 2. Re: shared sessionfactory between JBPM + Spring in SEAM
            spotlight2001
            [SOLVED]
            this is what i was looking for:
            http://www.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/4.3.0.cp02_fp01/html/Seam_Reference_Guide/ch10s03s02.html