11 Replies Latest reply on Mar 8, 2006 2:46 PM by Riccardo Palombella

    Spring is in the air

    James Depoorter Novice

      I guess there must be already some Spring integration initiatives. As we are heavily into Spring, we tried an integration as well. We have been using jBpm 3.1b2, because that looked like the easiest jBpm framework to "Springify" (the author has made it clear that the whole intention of 3.1 is more control over the configuration). I will not start any debate on strenghts and weaknesses of 3.1b2 and Spring, because "Unfortunately, I can't explain what jBpm 3.1b2 and Spring is, you have to see it for yourself".
      The goal of the integration was purely project-based:
      - features we will not use are not tested thoroughly, and are not injected/developed further (messaging, scheduler)
      - customization are in the scope of the project for which we tend to use jBpm
      However, we tried to made it non-intrusive: We subclassed were possible, we made factories and did a liiiiiittle bit of (Spring) AOP.
      I will copy/paste my todo list I used without changes:

      Create a custom jBpm ObjectFactory implementation which implements BeanFactoryAware also. Forward the getObject and hasObject to the BeanFactory methods
      Add a resource hashmap to ObjectFactory, for use as a store of simple configuration parameters (String, Long).
      Put hibernate configuration in Spring.
      Inject factory services in services bean
      Springify JpbmContext (singleton = FALSE !!). Inject services in it.
      Create a descendant of the DBPersistenceService, overriding the getters to use special create methods, for creating the session objects, so we can have custom implementation of the session objects at hand. Warning: these session objects are NOT bean-aware !! (As all non-singletons are).
      Create a custom PersistenceServiceFactory (override the one jBpm provides):

      create a "createService", which will use spring look-up to create a PersistenceService
      override openService, using the createService, which injects the session at runtime
      Inject the jbpm hibernate sessionfactory
      Inject the datasource

      Add a jbpm.task.instance.factory bean
      Add a jbpm.variable.resolver bean
      Create a JbpmConfigurationFactoryBean which will create a jbpmConfiguration (by using the Configs innerclass to set the defaultObjectFactory and getInstance to create it)
      Create a jbpmConfiguration Bean by using the JbpmConfigurationFactoryBean


      You then get this (rather elaborated) spring configuration:

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
      <beans>
      
       <bean id="jbpmSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
       parent="common.sessionFactory">
       <property name="dataSource">
       <ref bean="common.datasource" />
       </property>
       <property name="useTransactionAwareDataSource" value="true" />
       <property name="mappingResources">
       <list>
       <!-- graph.def mapping files -->
       <value>org/jbpm/graph/def/ProcessDefinition.hbm.xml</value>
       <value>org/jbpm/graph/def/Node.hbm.xml</value>
       <value>org/jbpm/graph/def/Transition.hbm.xml</value>
       <value>org/jbpm/graph/def/Event.hbm.xml</value>
       <value>org/jbpm/graph/def/Action.hbm.xml</value>
       <value>org/jbpm/graph/def/SuperState.hbm.xml</value>
       <value>org/jbpm/graph/def/ExceptionHandler.hbm.xml</value>
       <value>org/jbpm/instantiation/Delegation.hbm.xml</value>
      
       <!-- graph.node mapping files -->
       <value>org/jbpm/graph/node/StartState.hbm.xml</value>
       <value>org/jbpm/graph/node/EndState.hbm.xml</value>
       <value>org/jbpm/graph/node/ProcessState.hbm.xml</value>
       <value>org/jbpm/graph/node/Decision.hbm.xml</value>
       <value>org/jbpm/graph/node/Fork.hbm.xml</value>
       <value>org/jbpm/graph/node/Join.hbm.xml</value>
       <value>org/jbpm/graph/node/State.hbm.xml</value>
       <value>org/jbpm/graph/node/TaskNode.hbm.xml</value>
      
       <!-- context.def mapping files -->
       <value>org/jbpm/context/def/ContextDefinition.hbm.xml</value>
       <value>org/jbpm/context/def/VariableAccess.hbm.xml</value>
      
       <!-- taskmgmt.def mapping files -->
       <value>org/jbpm/taskmgmt/def/TaskMgmtDefinition.hbm.xml</value>
       <value>org/jbpm/taskmgmt/def/Swimlane.hbm.xml</value>
       <value>org/jbpm/taskmgmt/def/Task.hbm.xml</value>
       <value>org/jbpm/taskmgmt/def/TaskController.hbm.xml</value>
      
       <!-- module.def mapping files -->
       <value>org/jbpm/module/def/ModuleDefinition.hbm.xml</value>
      
       <!-- bytes mapping files -->
       <value>org/jbpm/bytes/ByteArray.hbm.xml</value>
      
       <!-- file.def mapping files -->
       <value>org/jbpm/file/def/FileDefinition.hbm.xml</value>
      
       <!-- scheduler.def mapping files -->
       <value>org/jbpm/scheduler/def/CreateTimerAction.hbm.xml</value>
       <value>org/jbpm/scheduler/def/CancelTimerAction.hbm.xml</value>
      
       <!-- graph.exe mapping files -->
       <value>org/jbpm/graph/exe/Comment.hbm.xml</value>
       <value>org/jbpm/graph/exe/ProcessInstance.hbm.xml</value>
       <value>org/jbpm/graph/exe/Token.hbm.xml</value>
       <value>org/jbpm/graph/exe/RuntimeAction.hbm.xml</value>
      
       <!-- module.exe mapping files -->
       <value>org/jbpm/module/exe/ModuleInstance.hbm.xml</value>
      
       <!-- context.exe mapping files -->
       <value>org/jbpm/context/exe/ContextInstance.hbm.xml</value>
       <value>org/jbpm/context/exe/TokenVariableMap.hbm.xml</value>
       <value>org/jbpm/context/exe/VariableInstance.hbm.xml</value>
       <value>org/jbpm/context/exe/variableinstance/ByteArrayInstance.hbm.xml</value>
       <value>org/jbpm/context/exe/variableinstance/DateInstance.hbm.xml</value>
       <value>org/jbpm/context/exe/variableinstance/DoubleInstance.hbm.xml</value>
       <value>org/jbpm/context/exe/variableinstance/HibernateLongInstance.hbm.xml</value>
       <value>org/jbpm/context/exe/variableinstance/HibernateStringInstance.hbm.xml</value>
       <value>org/jbpm/context/exe/variableinstance/LongInstance.hbm.xml</value>
       <value>org/jbpm/context/exe/variableinstance/StringInstance.hbm.xml</value>
      
       <!-- msg.db mapping files -->
       <value>org/jbpm/msg/Message.hbm.xml</value>
       <value>org/jbpm/msg/db/TextMessage.hbm.xml</value>
       <value>org/jbpm/command/ExecuteActionCommand.hbm.xml</value>
       <value>org/jbpm/command/ExecuteNodeCommand.hbm.xml</value>
       <value>org/jbpm/command/SignalCommand.hbm.xml</value>
       <value>org/jbpm/command/TaskInstanceEndCommand.hbm.xml</value>
      
       <!-- taskmgmt.exe mapping files -->
       <value>org/jbpm/taskmgmt/exe/TaskMgmtInstance.hbm.xml</value>
       <value>org/jbpm/taskmgmt/exe/TaskInstance.hbm.xml</value>
       <value>org/jbpm/taskmgmt/exe/PooledActor.hbm.xml</value>
       <value>org/jbpm/taskmgmt/exe/SwimlaneInstance.hbm.xml</value>
      
       <!-- scheduler.exe mapping files -->
       <value>org/jbpm/scheduler/exe/Timer.hbm.xml</value>
      
       <!-- logging mapping files -->
       <value>org/jbpm/logging/log/ProcessLog.hbm.xml</value>
       <value>org/jbpm/logging/log/MessageLog.hbm.xml</value>
       <value>org/jbpm/logging/log/CompositeLog.hbm.xml</value>
       <value>org/jbpm/graph/log/ActionLog.hbm.xml</value>
       <value>org/jbpm/graph/log/NodeLog.hbm.xml</value>
       <value>org/jbpm/graph/log/ProcessInstanceCreateLog.hbm.xml</value>
       <value>org/jbpm/graph/log/ProcessInstanceEndLog.hbm.xml</value>
       <value>org/jbpm/graph/log/SignalLog.hbm.xml</value>
       <value>org/jbpm/graph/log/TokenCreateLog.hbm.xml</value>
       <value>org/jbpm/graph/log/TokenEndLog.hbm.xml</value>
       <value>org/jbpm/graph/log/TransitionLog.hbm.xml</value>
       <value>org/jbpm/context/log/VariableLog.hbm.xml</value>
       <value>org/jbpm/context/log/VariableCreateLog.hbm.xml</value>
       <value>org/jbpm/context/log/VariableDeleteLog.hbm.xml</value>
       <value>org/jbpm/context/log/VariableUpdateLog.hbm.xml</value>
       <value>org/jbpm/context/log/variableinstance/ByteArrayUpdateLog.hbm.xml</value>
       <value>org/jbpm/context/log/variableinstance/DateUpdateLog.hbm.xml</value>
       <value>org/jbpm/context/log/variableinstance/DoubleUpdateLog.hbm.xml</value>
       <value>org/jbpm/context/log/variableinstance/HibernateLongUpdateLog.hbm.xml</value>
       <value>org/jbpm/context/log/variableinstance/HibernateStringUpdateLog.hbm.xml</value>
       <value>org/jbpm/context/log/variableinstance/LongUpdateLog.hbm.xml</value>
       <value>org/jbpm/context/log/variableinstance/StringUpdateLog.hbm.xml</value>
       <value>org/jbpm/taskmgmt/log/TaskLog.hbm.xml</value>
       <value>org/jbpm/taskmgmt/log/TaskCreateLog.hbm.xml</value>
       <value>org/jbpm/taskmgmt/log/TaskAssignLog.hbm.xml</value>
       <value>org/jbpm/taskmgmt/log/TaskEndLog.hbm.xml</value>
       <value>org/jbpm/taskmgmt/log/SwimlaneLog.hbm.xml</value>
       <value>org/jbpm/taskmgmt/log/SwimlaneCreateLog.hbm.xml</value>
       <value>org/jbpm/taskmgmt/log/SwimlaneAssignLog.hbm.xml</value>
      
       </list>
       </property>
       </bean>
      
       <bean id="transactionManagerJbpm" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <property name="dataSource">
       <ref bean="common.datasource" />
       </property>
       </bean>
      
       <bean id="jbpmObjectFactoryBeanFactoryAware" class="be.post.cits.ariane.jbpm.ObjectFactoryBeanFactoryAware">
       <property name="resources">
       <map>
       <entry key="resource.business.calendar">
       <value type="java.lang.String">org/jbpm/calendar/jbpm.business.calendar.properties</value>
       </entry>
       <entry key="resource.default.modules">
       <value type="java.lang.String">org/jbpm/graph/def/jbpm.default.modules.properties</value>
       </entry>
       <entry key="resource.converter">
       <value type="java.lang.String">org/jbpm/db/hibernate/jbpm.converter.properties</value>
       </entry>
       <entry key="resource.action.types">
       <value type="java.lang.String">org/jbpm/graph/action/action.types.xml</value>
       </entry>
       <entry key="resource.node.types">
       <value type="java.lang.String">org/jbpm/graph/node/node.types.xml</value>
       </entry>
       <entry key="resource.parsers">
       <value type="java.lang.String">org/jbpm/jpdl/par/jbpm.parsers.xml</value>
       </entry>
       <entry key="resource.varmapping">
       <value type="java.lang.String">org/jbpm/context/exe/jbpm.varmapping.xml</value>
       </entry>
       <entry key="jbpm.msg.wait.timout">
       <value type="java.lang.Long">5000</value>
       </entry>
       </map>
       </property>
       </bean>
      
       <bean id="dbPersistenceService" class="be.post.cits.ariane.jbpm.SpringDbPersistenceService" singleton="false">
       <property name="contextSessionClass" value="org.jbpm.db.ContextSession" />
       <property name="graphSessionClass" value="org.jbpm.db.GraphSession" />
       <property name="loggingSessionClass" value="org.jbpm.db.LoggingSession" />
       <property name="messagingSessionClass" value="org.jbpm.db.MessagingSession" />
       <property name="schedulerSessionClass" value="org.jbpm.db.SchedulerSession" />
       <property name="taskMgmtSessionClass" value="org.jbpm.db.TaskMgmtSession" />
       <constructor-arg>
       <ref local="persistenceServiceFactory" />
       </constructor-arg>
       </bean>
      
       <bean id="persistenceServiceFactory" class="be.post.cits.ariane.jbpm.SpringDbPersistenceServiceFactory">
       <lookup-method name="createPersistenceService" bean="dbPersistenceService" />
       <property name="dataSource">
       <ref bean="common.datasource" />
       </property>
       <property name="sessionFactory">
       <ref local="jbpmSessionFactory" />
       </property>
       <property name="localSessionFactoryBeanString">
       <idref bean="jbpmSessionFactory" />
       </property>
       </bean>
       <bean id="jbpmServices" class="org.jbpm.svc.Services">
       <constructor-arg>
       <map>
       <entry key="persistence">
       <ref local="persistenceServiceFactory"></ref>
       </entry>
       </map>
       </constructor-arg>
       </bean>
       <bean id="default.jbpm.context" singleton="false" class="org.jbpm.JbpmContext" name="jbpmContext">
       <constructor-arg>
       <ref local="jbpmServices" />
       </constructor-arg>
       <constructor-arg>
       <ref local="jbpmObjectFactoryBeanFactoryAware" />
       </constructor-arg>
       </bean>
       <bean id="jbpm.task.instance.factory" class="org.jbpm.taskmgmt.impl.DefaultTaskInstanceFactoryImpl" />
       <bean id="jbpm.variable.resolver" class="org.jbpm.jpdl.el.impl.JbpmVariableResolver" />
       <bean id="jbpmConfiguration" class="be.post.cits.ariane.jbpm.JbpmConfigurationFactoryBean">
       <property name="objectFactory">
       <ref local="jbpmObjectFactoryBeanFactoryAware" />
       </property>
       </bean>
      </beans>
      
      

      Of course, the hibernate mappings and other configuration could reside in an external file as well. Spring can refer to this file also. This file depends on other (not shown) configuration, e.g. for having a common datasource.
      Transactional behaviour is controlled by Spring or the application.

      Word to the author:
      - we need more setters :-) in favour of constructors.
      - alternatively, we need more "protected" instead of "package" (otherwise we have to define the same package structure, and this could be a project constraint).
      - we need more "design-by-interface". (We do some dangerous casting :-))

        • 1. Re: Spring is in the air
          Thomas Sandor Newbie

          Your integration TODO and beans xml seems to be great.

          Can you post your subclassed implementations? (e.g. jbpmObjectFactoryBeanFactoryAware, dbPersistenceService, persistenceServiceFactory, JbpmConfigurationFactoryBean)

          --
          Thomas

          • 2. Re: Spring is in the air
            James Depoorter Novice

            Of course. There was some glitches in the configuration for the session factory. It must depend on jbpmConfiguration, so:

            - depends-on="jbpmConfiguration" for the sessionFactory (believe me, it is necessary :-))
            - The addition of <value>my favorite directories:-)/hibernate.queries.hbm.xml</value> (the original has still errors (maybe other hibernate version), so I've made some changes)
            

            Maybe this could be a starting point of a subproject (or module). I have no "template" or the like.

            ObjectFactoryBeanFactoryAware
            package myFavoritePackage;
            import java.util.Map;
            import org.jbpm.configuration.ObjectFactory;
            import org.springframework.beans.BeansException;
            import org.springframework.beans.factory.BeanFactory;
            import org.springframework.beans.factory.BeanFactoryAware;
            
            public class ObjectFactoryBeanFactoryAware implements ObjectFactory, BeanFactoryAware {
            
             private BeanFactory beanFactory = null;
            
             private Map resources = null;
            
             public void setResources(Map resources) {
             this.resources = resources;
             }
            
             private Object getResource(String name) {
             return resources.get(name);
             }
            
             private boolean hasResource(String name) {
             return resources.containsKey(name);
             }
            
             public Object createObject(String name) {
             Object bean = getResource(name);
             if (bean == null) {
             bean = beanFactory.getBean(name);
             }
             return bean;
             }
            
             public boolean hasObject(String name) {
             boolean found = hasResource(name);
             if (!found) {
             found = beanFactory.containsBean(name);
             }
             return found;
             }
            
             public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
             this.beanFactory = beanFactory;
            
             }
            
            }
            

            SpringDbPersistenceService
            We did not care about transaction management in the close method, because we use transaction demarcation on another level
            If you really want to do this, it is easily extended
            package myFavoritePackage;
            
            import java.lang.reflect.Constructor;
            
            import org.hibernate.Session;
            import org.jbpm.db.ContextSession;
            import org.jbpm.db.GraphSession;
            import org.jbpm.db.LoggingSession;
            import org.jbpm.db.MessagingSession;
            import org.jbpm.db.SchedulerSession;
            import org.jbpm.db.TaskMgmtSession;
            import org.jbpm.persistence.db.DbPersistenceService;
            import org.jbpm.persistence.db.DbPersistenceServiceFactory;
            import org.springframework.orm.hibernate3.SessionFactoryUtils;
            
            public class SpringDbPersistenceService extends DbPersistenceService {
            
             private boolean isClosed = false;
             private Class graphSessionClass = null;
             private Class contextSessionClass = null;
             private Class loggingSessionClass = null;
             private Class messagingSessionClass = null;
             private Class schedulerSessionClass = null;
             private Class taskMgmtSessionClass = null;
            
             public void setContextSessionClass(String contextSessionClass) throws Exception {
             this.contextSessionClass = Class.forName(contextSessionClass);
             }
            
             public void setLoggingSessionClass(String loggingSessionClass) throws Exception {
             this.loggingSessionClass = Class.forName(loggingSessionClass);
             }
             public void setMessagingSessionClass(String messagingSessionClass) throws Exception {
             this.messagingSessionClass = Class.forName(messagingSessionClass);
             }
             public void setSchedulerSessionClass(String schedulerSessionClass) throws Exception {
             this.schedulerSessionClass = Class.forName(schedulerSessionClass);
             }
             public void setTaskMgmtSessionClass(String taskMgmtSessionClass) throws Exception {
             this.taskMgmtSessionClass = Class.forName(taskMgmtSessionClass);
             }
             public void setGraphSessionClass(String graphSessionClass) throws Exception {
             this.graphSessionClass = Class.forName(graphSessionClass);
             }
            
            
            
             SpringDbPersistenceService(DbPersistenceServiceFactory dbPersistenceServiceFactory) {
             super(dbPersistenceServiceFactory);
             }
            
             Object createDbSession(Class clazz) {
             try {
             Constructor constructor = clazz.getConstructor(new Class[] {Session.class});
             return constructor.newInstance(new Object[] {this.getSession()});
             } catch (Exception e) {
             throw new RuntimeException(e);
             }
             }
            
             public Object createDbSession(Class beanClass, Class defaultClass) {
             if (beanClass != null) {
             return createDbSession(beanClass);
             } else {
             return createDbSession(defaultClass);
             }
             }
            
            
             public GraphSession getGraphSession() {
             return (GraphSession) createDbSession(graphSessionClass,GraphSession.class);
             }
            
             public ContextSession getContextSession() {
             return (ContextSession) createDbSession(contextSessionClass,ContextSession.class);
             }
            
             public LoggingSession getLoggingSession() {
             return (LoggingSession) createDbSession(loggingSessionClass,LoggingSession.class);
             }
            
             public MessagingSession getMessagingSession() {
             return (MessagingSession) createDbSession(messagingSessionClass,MessagingSession.class);
             }
            
             public SchedulerSession getSchedulerSession() {
             return (SchedulerSession) createDbSession(schedulerSessionClass,SchedulerSession.class);
             }
            
             public TaskMgmtSession getTaskMgmtSession() {
             return (TaskMgmtSession) createDbSession(taskMgmtSessionClass,TaskMgmtSession.class);
             }
            
             // try releasing the session
             public void close() {
             // only allow a close once
             if (!isClosed) {
             SessionFactoryUtils.releaseSession(getSession(), getSessionFactory());
             isClosed = true;
             }
             }
            }
            


            SpringDbPersistenceServiceFactory
            package MyFavoritePackage;
            
            import org.jbpm.persistence.db.DbPersistenceService;
            import org.jbpm.persistence.db.DbPersistenceServiceFactory;
            import org.jbpm.svc.Service;
            import org.springframework.beans.BeansException;
            import org.springframework.beans.factory.BeanFactory;
            import org.springframework.beans.factory.BeanFactoryAware;
            import org.springframework.beans.factory.InitializingBean;
            import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
            import org.springframework.orm.hibernate3.SessionFactoryUtils;
            import org.springframework.transaction.PlatformTransactionManager;
            import org.springframework.transaction.support.TransactionTemplate;
            
            public class SpringDbPersistenceServiceFactory extends DbPersistenceServiceFactory implements InitializingBean,BeanFactoryAware {
            
             // lookup method, replaced by spring
             // will return a DbPersistenceService, implementing Service as well
            
             private String localSessionFactoryBeanString;
             private BeanFactory beanFactory;
            
            
            
             public void setLocalSessionFactoryBeanString(String localSessionFactoryBeanString) {
             if (localSessionFactoryBeanString.startsWith("&")) {
             this.localSessionFactoryBeanString = localSessionFactoryBeanString;
             } else {
             this.localSessionFactoryBeanString = "&" + localSessionFactoryBeanString;
             }
             }
            
            
             public DbPersistenceService createPersistenceService() {
             return null;
             }
            
            
             public Service openService() {
             // TODO Auto-generated method stub
             Service service = createPersistenceService();
             DbPersistenceService persistenceService = (DbPersistenceService) service;
             // create session if necessary
             persistenceService.setSession(SessionFactoryUtils.getSession(getSessionFactory(),true));
             return service;
             }
            
             public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
             this.beanFactory = beanFactory;
            
             }
             public void afterPropertiesSet() throws Exception {
             this.setConfiguration(((LocalSessionFactoryBean) beanFactory.getBean(localSessionFactoryBeanString)).getConfiguration());
             }
            }
            


            JbpmConfigurationFactoryBean
            package MyFavoritePackage;
            
            import org.jbpm.JbpmConfiguration;
            import org.jbpm.configuration.ObjectFactory;
            import org.springframework.beans.factory.FactoryBean;
            
            public class JbpmConfigurationFactoryBean implements FactoryBean {
            
             private ObjectFactory objectFactory;
            
             public void setObjectFactory(ObjectFactory objectFactory) {
             this.objectFactory = objectFactory;
             }
            
             public Class getObjectType() {
             return JbpmConfiguration.class;
            }
            
             public boolean isSingleton() {
             return true;
             }
            
             public Object getObject() throws Exception {
             JbpmConfiguration.Configs.setDefaultObjectFactory(objectFactory);
             return JbpmConfiguration.getInstance();
             }
            }
            



            • 3. Re: Spring is in the air
              Costin Leau Newbie

              Not sure if you are aware but there is already jbpm integration code available as part of Spring Modules (springmodules.dev.java.net).
              Jbpm 3.1 has been already integrated but needs more tests - the code will be committed in the upcoming days.
              See the forums for more information : http://forum.springframework.org/forumdisplay.php?f=37

              The current code allows actions to be declared and injected from Spring application context. It is possible to use either a Spring application context or a configuration file for your jbpm configuration.

              One nice feature is that it integrates with Spring transaction support.
              You can find the current jbpm 3.0 code here: http://cvs.sourceforge.net/viewcvs.py/springframework/spring-projects/spring-jbpm/

              In the upcoming days the jbpm 3.0 and 3.1 integration code will be moved to Spring Modules.

              • 4. Re: Spring is in the air
                edgar poce Newbie

                good work costin!!!

                br,
                edgar

                • 5. Re: Spring is in the air
                  Haocheng Yuan Newbie

                   

                  "Costin" wrote:
                  Not sure if you are aware but there is already jbpm integration code available as part of Spring Modules (springmodules.dev.java.net).
                  Jbpm 3.1 has been already integrated but needs more tests - the code will be committed in the upcoming days.
                  See the forums for more information : http://forum.springframework.org/forumdisplay.php?f=37

                  The current code allows actions to be declared and injected from Spring application context. It is possible to use either a Spring application context or a configuration file for your jbpm configuration.

                  One nice feature is that it integrates with Spring transaction support.
                  You can find the current jbpm 3.0 code here: http://cvs.sourceforge.net/viewcvs.py/springframework/spring-projects/spring-jbpm/

                  In the upcoming days the jbpm 3.0 and 3.1 integration code will be moved to Spring Modules.


                  I have looked jbpm 3.0 code ,please show some code for jbpm3.1 integration ?
                  Thank you

                  • 6. Re: Spring is in the air
                    Haocheng Yuan Newbie

                     

                    "icyjamie" wrote:
                    <li>Springify JpbmContext (singleton = FALSE !!). Inject services in it.</li>

                    I want to know why you set JbpmContext not singleton ?

                    And I run a test, But in the method popThisContextFromTheStack of JpbmContext , it throw exception

                    Could you give me some advice?

                    Thank you!


                    • 7. Re: Spring is in the air
                      Costin Leau Newbie

                       

                      I have looked jbpm 3.0 code ,please show some code for jbpm3.1 integration ?
                      Thank you

                      I'll commit the code in Spring Modules repository in the upcoming days (today dev.java.net CVS is down for maintainance).

                      • 8. Re: Spring is in the air
                        Administrator Administrator Novice

                        in case you didn't see it yet, there is a opportunity for the jbpm spring integration with the expressions.

                        jBPM 3.1 introduced the expressions. actions, assignment handler and decision handlers can be referenced via a JSF/JSP-like EL expression language. The VariableResolver is customizable. So in a spring environment, the VariableResolver could be extended to search for the variables in the spring beans xml. So you could define your delegation classes in spring instead of in the process...

                        regards, tom.

                        • 9. Re: Spring is in the air
                          jbpmndc Newbie

                          You can view the latest Spring code in CVS
                          http://cvs.sourceforge.net/viewcvs.py/springframework/spring-projects/spring-jbpm/

                          There is a JBPMTemplate class that seems similar to HibernateTemplate

                          • 10. Re: Spring is in the air
                            rosen jiang Newbie

                            integration with Spring, we need it!

                            • 11. Re: Spring is in the air
                              Riccardo Palombella Newbie

                               

                              "icyjamie" wrote:
                              Of course. There was some glitches in the configuration for the session factory. It must depend on jbpmConfiguration, so:
                              - depends-on="jbpmConfiguration" for the sessionFactory (believe me, it is necessary :-))
                              - The addition of <value>my favorite directories:-)/hibernate.queries.hbm.xml</value> (the original has still errors (maybe other hibernate version), so I've made some changes)
                              

                              Maybe this could be a starting point of a subproject (or module). I have no "template" or the like.

                              ObjectFactoryBeanFactoryAware
                              package myFavoritePackage;
                              import java.util.Map;
                              import org.jbpm.configuration.ObjectFactory;
                              import org.springframework.beans.BeansException;
                              import org.springframework.beans.factory.BeanFactory;
                              import org.springframework.beans.factory.BeanFactoryAware;
                              
                              public class ObjectFactoryBeanFactoryAware implements ObjectFactory, BeanFactoryAware {
                              
                               private BeanFactory beanFactory = null;
                              
                               private Map resources = null;
                              
                               public void setResources(Map resources) {
                               this.resources = resources;
                               }
                              
                               private Object getResource(String name) {
                               return resources.get(name);
                               }
                              
                               private boolean hasResource(String name) {
                               return resources.containsKey(name);
                               }
                              
                               public Object createObject(String name) {
                               Object bean = getResource(name);
                               if (bean == null) {
                               bean = beanFactory.getBean(name);
                               }
                               return bean;
                               }
                              
                               public boolean hasObject(String name) {
                               boolean found = hasResource(name);
                               if (!found) {
                               found = beanFactory.containsBean(name);
                               }
                               return found;
                               }
                              
                               public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
                               this.beanFactory = beanFactory;
                              
                               }
                              
                              }
                              

                              SpringDbPersistenceService
                              We did not care about transaction management in the close method, because we use transaction demarcation on another level
                              If you really want to do this, it is easily extended
                              package myFavoritePackage;
                              
                              import java.lang.reflect.Constructor;
                              
                              import org.hibernate.Session;
                              import org.jbpm.db.ContextSession;
                              import org.jbpm.db.GraphSession;
                              import org.jbpm.db.LoggingSession;
                              import org.jbpm.db.MessagingSession;
                              import org.jbpm.db.SchedulerSession;
                              import org.jbpm.db.TaskMgmtSession;
                              import org.jbpm.persistence.db.DbPersistenceService;
                              import org.jbpm.persistence.db.DbPersistenceServiceFactory;
                              import org.springframework.orm.hibernate3.SessionFactoryUtils;
                              
                              public class SpringDbPersistenceService extends DbPersistenceService {
                              
                               private boolean isClosed = false;
                               private Class graphSessionClass = null;
                               private Class contextSessionClass = null;
                               private Class loggingSessionClass = null;
                               private Class messagingSessionClass = null;
                               private Class schedulerSessionClass = null;
                               private Class taskMgmtSessionClass = null;
                              
                               public void setContextSessionClass(String contextSessionClass) throws Exception {
                               this.contextSessionClass = Class.forName(contextSessionClass);
                               }
                              
                               public void setLoggingSessionClass(String loggingSessionClass) throws Exception {
                               this.loggingSessionClass = Class.forName(loggingSessionClass);
                               }
                               public void setMessagingSessionClass(String messagingSessionClass) throws Exception {
                               this.messagingSessionClass = Class.forName(messagingSessionClass);
                               }
                               public void setSchedulerSessionClass(String schedulerSessionClass) throws Exception {
                               this.schedulerSessionClass = Class.forName(schedulerSessionClass);
                               }
                               public void setTaskMgmtSessionClass(String taskMgmtSessionClass) throws Exception {
                               this.taskMgmtSessionClass = Class.forName(taskMgmtSessionClass);
                               }
                               public void setGraphSessionClass(String graphSessionClass) throws Exception {
                               this.graphSessionClass = Class.forName(graphSessionClass);
                               }
                              
                              
                              
                               SpringDbPersistenceService(DbPersistenceServiceFactory dbPersistenceServiceFactory) {
                               super(dbPersistenceServiceFactory);
                               }
                              
                               Object createDbSession(Class clazz) {
                               try {
                               Constructor constructor = clazz.getConstructor(new Class[] {Session.class});
                               return constructor.newInstance(new Object[] {this.getSession()});
                               } catch (Exception e) {
                               throw new RuntimeException(e);
                               }
                               }
                              
                               public Object createDbSession(Class beanClass, Class defaultClass) {
                               if (beanClass != null) {
                               return createDbSession(beanClass);
                               } else {
                               return createDbSession(defaultClass);
                               }
                               }
                              
                              
                               public GraphSession getGraphSession() {
                               return (GraphSession) createDbSession(graphSessionClass,GraphSession.class);
                               }
                              
                               public ContextSession getContextSession() {
                               return (ContextSession) createDbSession(contextSessionClass,ContextSession.class);
                               }
                              
                               public LoggingSession getLoggingSession() {
                               return (LoggingSession) createDbSession(loggingSessionClass,LoggingSession.class);
                               }
                              
                               public MessagingSession getMessagingSession() {
                               return (MessagingSession) createDbSession(messagingSessionClass,MessagingSession.class);
                               }
                              
                               public SchedulerSession getSchedulerSession() {
                               return (SchedulerSession) createDbSession(schedulerSessionClass,SchedulerSession.class);
                               }
                              
                               public TaskMgmtSession getTaskMgmtSession() {
                               return (TaskMgmtSession) createDbSession(taskMgmtSessionClass,TaskMgmtSession.class);
                               }
                              
                               // try releasing the session
                               public void close() {
                               // only allow a close once
                               if (!isClosed) {
                               SessionFactoryUtils.releaseSession(getSession(), getSessionFactory());
                               isClosed = true;
                               }
                               }
                              }
                              


                              SpringDbPersistenceServiceFactory
                              package MyFavoritePackage;
                              
                              import org.jbpm.persistence.db.DbPersistenceService;
                              import org.jbpm.persistence.db.DbPersistenceServiceFactory;
                              import org.jbpm.svc.Service;
                              import org.springframework.beans.BeansException;
                              import org.springframework.beans.factory.BeanFactory;
                              import org.springframework.beans.factory.BeanFactoryAware;
                              import org.springframework.beans.factory.InitializingBean;
                              import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
                              import org.springframework.orm.hibernate3.SessionFactoryUtils;
                              import org.springframework.transaction.PlatformTransactionManager;
                              import org.springframework.transaction.support.TransactionTemplate;
                              
                              public class SpringDbPersistenceServiceFactory extends DbPersistenceServiceFactory implements InitializingBean,BeanFactoryAware {
                              
                               // lookup method, replaced by spring
                               // will return a DbPersistenceService, implementing Service as well
                              
                               private String localSessionFactoryBeanString;
                               private BeanFactory beanFactory;
                              
                              
                              
                               public void setLocalSessionFactoryBeanString(String localSessionFactoryBeanString) {
                               if (localSessionFactoryBeanString.startsWith("&")) {
                               this.localSessionFactoryBeanString = localSessionFactoryBeanString;
                               } else {
                               this.localSessionFactoryBeanString = "&" + localSessionFactoryBeanString;
                               }
                               }
                              
                              
                               public DbPersistenceService createPersistenceService() {
                               return null;
                               }
                              
                              
                               public Service openService() {
                               // TODO Auto-generated method stub
                               Service service = createPersistenceService();
                               DbPersistenceService persistenceService = (DbPersistenceService) service;
                               // create session if necessary
                               persistenceService.setSession(SessionFactoryUtils.getSession(getSessionFactory(),true));
                               return service;
                               }
                              
                               public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
                               this.beanFactory = beanFactory;
                              
                               }
                               public void afterPropertiesSet() throws Exception {
                               this.setConfiguration(((LocalSessionFactoryBean) beanFactory.getBean(localSessionFactoryBeanString)).getConfiguration());
                               }
                              }
                              


                              JbpmConfigurationFactoryBean
                              package MyFavoritePackage;
                              
                              import org.jbpm.JbpmConfiguration;
                              import org.jbpm.configuration.ObjectFactory;
                              import org.springframework.beans.factory.FactoryBean;
                              
                              public class JbpmConfigurationFactoryBean implements FactoryBean {
                              
                               private ObjectFactory objectFactory;
                              
                               public void setObjectFactory(ObjectFactory objectFactory) {
                               this.objectFactory = objectFactory;
                               }
                              
                               public Class getObjectType() {
                               return JbpmConfiguration.class;
                              }
                              
                               public boolean isSingleton() {
                               return true;
                               }
                              
                               public Object getObject() throws Exception {
                               JbpmConfiguration.Configs.setDefaultObjectFactory(objectFactory);
                               return JbpmConfiguration.getInstance();
                               }
                              }