Announcement Announcement Module
Collapse

Spring Modules forum decommissioned in favor of Spring Extensions

As the Spring Modules project has been replaced by the Spring Extensions (http://www.springsource.org/extensions) project, this forum has been decommissioned in favour of Spring Extensions one at:
http://forum.springsource.org/forumdisplay.php?f=44

Please see the Spring Extensions home page for a complete list of current projects in Java, .NET and ActionScript. You can also propose one if you want.

Cheers,
Costin Leau
SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
http://twitter.com/costinl
See more
See less
JBPM scheduler Integration Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JBPM scheduler Integration

    Hello,

    I am wondering about the integration of the JBPM DB scheduler service from spring modules.

    I do have the jbpm.cfg.xml file with an entry for the scheduler service as :
    Code:
      	<service name="scheduler" factory="org.jbpm.scheduler.db.DbSchedulerServiceFactory" />
    and I had this understanding that the service will be started as part of the LocalJbpmConfigurationFactoryBean implementation but it just starts the persistence service not the scheduler service.

    Wondering how to go about the integration of this service from Spring world?

    Thanks,
    Arshad

  • #2
    Update

    A little more info in this regard, we tried SchedulerServlet from JBPM but it starts building its own session factory etc independent of the one we configured through spring.

    This is like having a parallel configuration based on JBPM instead of spring to run the scheduler.

    So, now, i am realising there is huge need to have this JBPM Scheduler (scheduler servlet or the DB Scheduler service) integrated in the spring modules.

    Let me know if you need any further info?

    Thanks,
    Arshad

    Comment


    • #3
      Any Idea how to do that?

      Thanx & regards
      Milan

      Comment


      • #4
        integerate timer with spring modules

        hi dears

        i create new class like this write all codes in JbpmThreadsServlet)

        public class TimerBean implements InitializingBean {

        private JbpmConfiguration jbpmConfiguration = null;
        private CommandExecutorThread commandExecutorThread = null;
        private SchedulerThread schedulerThread = null;

        public void afterPropertiesSet() throws Exception {
        // get the jbpm configuration resource
        commandExecutorThread = new CommandExecutorThread(jbpmConfiguration);
        commandExecutorThread.start();

        schedulerThread = new SchedulerThread(jbpmConfiguration);
        schedulerThread.start();
        }

        public JbpmConfiguration getJbpmConfiguration() {
        return jbpmConfiguration;
        }

        public void setJbpmConfiguration(JbpmConfiguration jbpmConfiguration) {
        this.jbpmConfiguration = jbpmConfiguration;
        }

        }

        and add TimerBean to spring like this :

        <?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="timerBean" class="TimerBean">
        <property name="jbpmConfiguration" ref="jbpmConfiguration"/>
        </bean>
        </beans>

        and finish my and your problem.

        Comment


        • #5
          Complete code + update

          Thanks for posting a solution m8 - but you forgot to tell us that any action related to the SchedulerThread/Service should be done when a valid JbpmContext is available e.g. :

          Code:
                          /** remember - t1 WON'T be valid after you get out of the execute() method.... since the context is only valid for the duration you stay inside that method, any jbpm method you execute that requires the context (inside the domain of spring, OR even outside) will have access to it. */
          
          		JbpmContext t1 = (JbpmContext)getJbpmTemplate().execute(new JbpmCallback() {
          		     public Object doInJbpm(JbpmContext context) {
          		      // do something
          		    	 ProcessInstance processInstance = context.getProcessInstance(instanceId);
          		 		log.debug("found process...");
          				processInstance.signal();
          				log.debug("signalled process...");
          				context.save(processInstance);
          				log.debug("saved process...");
          		    	 return JbpmContext.getCurrentJbpmContext(); // statement not really needed - you can return null, or even monkey for all I care.
          		     }
          		  });

          In contrast, if you had something like this:

          Code:
                          // this caused me too much misery with a timer node.... will never work!
          		ProcessInstance processInstance = jbpmTemplate.findProcessInstance(instanceId);
          		log.debug("found process...");
          		processInstance.signal();
          		log.debug("signalled process...");
          		jbpmTemplate.saveProcessInstance(processInstance);
          		log.debug("saved process...");
          It won't work as the context would be closed for some reason when the Scheduler code was reached.... and when that happened, I debugged the code and found out where it was failing and then printing a BIG FAT 'service "scheduler" not available OOHH Exception bla bla blady bla' :

          Code:
           // code from org.jbpm.svc.Services
          
            public static Service getCurrentService(String name) {
             return getCurrentService(name, true); 
            }
            
            public static Service getCurrentService(String name, boolean isRequired) {
              Service service = null;
          
              // this was coming in as null !!!! No context means no service - mommyyyyy!!!
              JbpmContext jbpmContext = JbpmContext.getCurrentJbpmContext();
              if (jbpmContext!=null) {
                service = jbpmContext.getServices().getService(name);
              }
              if (isRequired && (service==null)) {
                throw new JbpmServiceException("service '"+name+"' unavailable");
              }
              return service;
            }
          So everything is working A-OK now. For people who want to integrate the scheduler service, I have attached the full code here:

          Code:
          // applicationContext.xml
          
          <?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:aop="http://www.springframework.org/schema/aop"
          	xmlns:tx="http://www.springframework.org/schema/tx"
          	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
                     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
          
          	<!-- JBPM Datasource -->
          	<bean id="jbpmDataSource"
          		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
          		<property name="driverClassName">
          			<value>com.mysql.jdbc.Driver</value>
          		</property>
          		<property name="url">
          			<value>
          				jdbc:mysql://localhost:3306/jbpmtest?useUnicode=true&amp;characterEncoding=UTF-8
          			</value>
          		</property>
          		<property name="username">
          			<value>jbpm</value>
          		</property>
          		<property name="password">
          			<value>jbpm</value>
          		</property>
          	</bean>
          
          	<bean id="mysqlHibernateProperties"
          		class="org.springframework.beans.factory.config.PropertiesFactoryBean">
          		<property name="properties">
          			<props>
          				<prop key="hibernate.dialect">
          					org.hibernate.dialect.MySQLDialect
          				</prop>
          				<prop key="hibernate.cache.provider_class">
          					org.hibernate.cache.HashtableCacheProvider
          				</prop>
          				<prop key="hibernate.default_batch_fetch_size">30</prop>
          				<prop key="hibernate.cache.use_query_cache">false</prop>
          			</props>
          		</property>
          	</bean>
          
          
          	<!-- JBPM Hibernate SessionFactory -->
          	<bean id="sessionFactory"
          		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
          		<property name="dataSource" ref="jbpmDataSource" />
          		<property name="hibernateProperties"
          			ref="mysqlHibernateProperties" />
          		<property name="mappingLocations">
          			<value>classpath*:/org/jbpm/**/*.hbm.xml</value>
          		</property>
          	</bean>
          
          	<bean id="txManager"
          		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
          		<property name="sessionFactory" ref="sessionFactory" />
          	</bean>
          
          	<!-- helper for reading jBPM process definitions -->
          	<bean id="simpleWorkflow"
          		class="org.springmodules.workflow.jbpm31.definition.ProcessDefinitionFactoryBean">
          		<property name="definitionLocation"
          			value="classpath:com/arc/jbpmtest/sample/jpdl/simpleWorkflow/processdefinition.xml" />
          	</bean>
          
          
          	<!-- jBPM configuration -->
          	<!-- use this instead in production 
          		<bean id="jbpmConfig" class="arc.jbpmtest.CustomLocalJbpmConfigurationFactoryBean">
          	-->
          	<bean id="jbpmConfiguration"
          		class="org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean">
          		<property name="sessionFactory" ref="sessionFactory" />
          		<property name="configuration"
          			value="classpath:jbpm.cfg.xml" />
          		<property name="createSchema" value="false" />
          		<property name="processDefinitions">
          			<list>
          				<ref local="simpleWorkflow" />
          			</list>
          		</property>
          		<!--
          			<property name="processDefinitionsResources">
          			<list>
          			<value>classpath:/org/springmodules/workflow/jbpm31/someOtherWorkflow.xml</value>
          			</list>
          			</property>
          		-->
          	</bean>
          
          	<!-- jBPM template -->
          	<bean id="jbpmTemplate"
          		class="org.springmodules.workflow.jbpm31.JbpmTemplate">
          		<constructor-arg index="0" ref="jbpmConfiguration" />
          		<constructor-arg index="1" ref="simpleWorkflow" />
          	</bean>
          
          	<bean id="workflowServiceTarget"
          		class="com.arc.jbpmtest.sample.base.workflow.WorkflowService"
          		autowire="byName">
          		<property name="jbpmTemplate" ref="jbpmTemplate" />
          	</bean>
          	<bean id="workflowService"
          		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
          		<property name="transactionManager" ref="txManager" />
          		<property name="target" ref="workflowServiceTarget" />
          		<property name="proxyTargetClass" value="true" />
          		<property name="transactionAttributes">
          			<props>
          				<prop key="*">PROPAGATION_NESTED</prop>
          			</props>
          		</property>
          	</bean>
          	<bean id="myMessageActionHandler"
          		class="com.arc.jbpmtest.sample.action.MessageActionHandler">
          		<property name="message"
          			value="This Message is Spring Injected!" />
          	</bean>
          	<bean id="workflowController"
          		class="com.arc.jbpmtest.beans.WorkflowController" scope="session">
          		<property name="workflowService" ref="workflowService" />
          	</bean>
          	<bean id="timerBean" class="com.arc.jbpmtest.servlets.JbpmThreadsServlet$TimerBean">
          		<property name="jbpmConfiguration" ref="jbpmConfiguration" />
          		<property name="jbpmTemplate" ref="jbpmTemplate" />
          	</bean>
          </beans>

          Comment


          • #6
            Code:
            // WorkflowService
            package com.arc.jbpmtest.sample.base.workflow;
            
            import java.util.ArrayList;
            import java.util.HashMap;
            import java.util.Iterator;
            import java.util.List;
            import java.util.Map;
            
            import org.apache.log4j.Logger;
            import org.jbpm.JbpmConfiguration;
            import org.jbpm.JbpmContext;
            import org.jbpm.graph.exe.ProcessInstance;
            import org.jbpm.svc.JbpmServiceException;
            import org.jbpm.svc.Services;
            import org.springmodules.workflow.jbpm31.JbpmCallback;
            import org.springmodules.workflow.jbpm31.JbpmTemplate;
            
            public class WorkflowService {
            
            	/**
            	 * Logger for this class
            	 */
            	private static final Logger log = Logger.getLogger(WorkflowService.class);
            	
            	private JbpmTemplate jbpmTemplate; 
            	
            	public WorkflowService() {
            		log.debug("WorkflowService()");
            	}
            	
            	public List<ProcessInstanceItem> getProcessInstances() {
            		log.debug("Enter getProcessInstances()");
            		
            		log.debug("About to get list of instances");
            		List<ProcessInstance> lst = jbpmTemplate.findProcessInstances();
            		log.debug("Got list - list has " + lst.size() + "elements.." );
            		
            		List<ProcessInstanceItem> processInstanceItems = new ArrayList<ProcessInstanceItem>();
            		
            		for (Iterator iter1 = lst.iterator(); iter1.hasNext();) {
            			log.debug("Entered loop" );
            			ProcessInstance element = (ProcessInstance) iter1.next();
            			log.debug("Got element..." );
            			ProcessInstanceItem item = new ProcessInstanceItem();
            			item.setDefName(element.getProcessDefinition().getName());
            			log.debug("Got name..." );
            			item.setEnd(element.getEnd());
            			log.debug("Got end..." );
            			item.setIdentifier(element.getId());
            			log.debug("Got Id..." );
            			item.setMessage("Dummy Message"/*(String)(element.getContextInstance().getVariables().get("message"))*/);
            			log.debug("Got message..." );
            			item.setNodeName(element.getRootToken().getNode().getName());
            			log.debug("Got Node name..." );
            			item.setStarted(element.getStart());
            			log.debug("Got Start..." );
            			processInstanceItems.add(item);	
            		}
            		
            		
            		return processInstanceItems;
            		
            	} 
            	
            	public ProcessInstance getNewProcessInstance() {
            		
            		log.debug("in getNewProcessInstance()");
            		log.debug("creating processInstance");
            		ProcessInstance processInstance = jbpmTemplate.getProcessDefinition().createProcessInstance();
            		log.debug("after creating processInstance");
            		jbpmTemplate.saveProcessInstance(processInstance);
            		log.debug("saved instance... processInstance");
            		return processInstance;
            		
            	} 
            	
            	public void signalProcessInstance(final Long instanceId) {
            		log.debug("in signalProcessInstance()");
            		
            
            		JbpmContext t1 = (JbpmContext)getJbpmTemplate().execute(new JbpmCallback() {
            		     public Object doInJbpm(JbpmContext context) {
            		      // do something
            		    	 ProcessInstance processInstance = context.getProcessInstance(instanceId);
            		 		log.debug("found process...");
            				processInstance.signal();
            				log.debug("signalled process...");
            				context.save(processInstance);
            				log.debug("saved process...");
            		    	 return JbpmContext.getCurrentJbpmContext();
            		     }
            		  });
            		
            		/*ProcessInstance processInstance = jbpmTemplate.findProcessInstance(instanceId);
            		log.debug("found process...");
            		processInstance.signal();
            		log.debug("signalled process...");
            		jbpmTemplate.saveProcessInstance(processInstance);
            		log.debug("saved process...");*/
            	}
            	
            	public JbpmTemplate getJbpmTemplate() {
            		log.debug("in getJbpmTemplate()");
            
            		return jbpmTemplate;
            	}
            
            	public void setJbpmTemplate(JbpmTemplate jbpmTemplate) {
            		log.debug("in setJbpmTemplate(JbpmTemplate jbpmTemplate)");
            		log.debug("jbpmTemplate is " + jbpmTemplate.getContextName());
            		this.jbpmTemplate = jbpmTemplate;
            	}
            
            	
            }

            Comment


            • #7
              Code:
              // JbpmThreadsServlet
              
              
              package com.arc.jbpmtest.servlets;
              
              import javax.servlet.http.HttpServletRequest;
              import javax.servlet.http.HttpServletResponse;
              
              import org.apache.log4j.Logger;
              import org.jbpm.JbpmConfiguration;
              import org.jbpm.msg.command.CommandExecutorThread;
              import org.jbpm.scheduler.impl.SchedulerThread;
              import org.springframework.beans.factory.InitializingBean;
              import org.springframework.web.servlet.FrameworkServlet;
              import org.springmodules.workflow.jbpm31.JbpmTemplate;
              import org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean;
              
              public class JbpmThreadsServlet extends FrameworkServlet {
              
              	private static final Logger log = Logger.getLogger(JbpmThreadsServlet.class);
              	
              	private static final long serialVersionUID = 1L;
              
              	CommandExecutorThread commandExecutorThread = null;
              	SchedulerThread schedulerThread = null;
              	
              	public JbpmThreadsServlet(){
              		
              	}
              	
              	@Override
              	protected void doService(HttpServletRequest req, HttpServletResponse resp)
              			throws Exception {
              		
              	}
              
              	private void initialize() {
              		
              	}
              
              	protected void initFrameworkServlet(){
              		initialize();
              	}
              	
              	public void destroy(){
              	    super.destroy();
              	    
              	    TimerBean timerBean  = (TimerBean)getWebApplicationContext().getBean("timerBean");
              	    
              		if(getWebApplicationContext().containsBean("timerBean")){
              			log.debug("Found timerBean, destroying threads...");
              		}
              		else
              			log.debug("Could not find timerBean, could not destroy threads.");
              		
              		timerBean.destroy();
              	}
              	
              	protected String getInitParameter(String name, String defaultValue) {
              		String value = getInitParameter(name);
              		if (value!=null) {
              			return value;
              		}
              		return defaultValue;
              	}
              	
              	static public class TimerBean implements InitializingBean {
              
              		private JbpmConfiguration jbpmConfiguration = null;
              		private CommandExecutorThread commandExecutorThread = null;
              		private SchedulerThread schedulerThread = null;
              		private JbpmTemplate jbpmTemplate = null;
              
              		public TimerBean(){
              			
              		} 
              		public void afterPropertiesSet() throws Exception {
              //			get the jbpm configuration resource
              			commandExecutorThread = new CommandExecutorThread(jbpmTemplate.getJbpmConfiguration());
              			commandExecutorThread.start();
              
              			schedulerThread = new SchedulerThread(jbpmTemplate.getJbpmConfiguration());
              			schedulerThread.start();
              			
              		    if(schedulerThread.isAlive())
              		    	log.debug("Scheduler Thread started successfully.");
              		    else
              		    	log.debug("Could not start Scheduler Thread.");
              		    
              		    if(commandExecutorThread.isAlive())
              		    	log.debug("Command Executor Thread started successfully.");
              		    
              		    else
              		    	log.debug("Could not start Command Executor Thread.");
              			
              		}
              		
              		public void destroy(){
              		    if ( (schedulerThread!=null)
              		         && (schedulerThread.isAlive())
              		       ) {
              		      schedulerThread.quit();
              		    }
              		    if ( (commandExecutorThread!=null)
              		        && (commandExecutorThread.isAlive())
              		      ) {
              		      commandExecutorThread.quit();
              		   }
              		}
              
              		public JbpmConfiguration getJbpmConfiguration() {
              			return jbpmConfiguration;
              		}
              
              		public void setJbpmConfiguration(JbpmConfiguration jbpmConfiguration) {
              			this.jbpmConfiguration = jbpmConfiguration;
              		}
              		public JbpmTemplate getJbpmTemplate() {
              			return jbpmTemplate;
              		}
              		public void setJbpmTemplate(JbpmTemplate jbpmTemplate) {
              			this.jbpmTemplate = jbpmTemplate;
              		}
              
              	}
              	
              }
              Last edited by neo_x; May 28th, 2007, 06:10 PM. Reason: missed a starting [ for the [code] tag... doh

              Comment


              • #8
                I'm having the exact same problem (springmodules 0.9, jBPM-3.2.3): context is null and I traced it down to the same source as you did.

                I tried implementing neo_x's solution but it makes use of classes that are no longer existent in the current jBPM releases (msg.command.CommandExecutorThread, scheduler.impl.SchedulerThread). I added them manually to the jar-file but this seems to have all sorts of weird effects and breaks things.

                An important point of interest is if someone is using the scheduler-feature successfully in springmodules. Anyone?

                Comment

                Working...
                X