4 Replies Latest reply on Oct 12, 2007 8:21 AM by kukeltje

    [HOW-TO] Programmatically create and cancel Timers

    sonicfab

      I spent some time on finding out how to programmatically create and cancel timers, so I thought it might be a good idea to share this with you.
      (Note : this works with jBPM-jPDL 3.2.1 and 3.2.2).

      1- Define a scheduler service in jbpm.cfg.xml :

      <service name="scheduler"
       factory="org.jbpm.scheduler.db.DbSchedulerServiceFactory" />


      2- Start a job executor thread (we do it via Spring) :
      <!-- Jbpm job executor -->
       <bean name="jbpm.job.executor" class="org.jbpm.job.executor.JobExecutor">
       <field name="jbpmConfiguration"><ref bean="jbpmConfiguration" /></field>
       <field name="name"><string value="JbpmJobExector" /></field>
       <field name="nbrOfThreads"><int value="1" /></field>
       <field name="idleInterval"><int value="5000" /></field>
       <field name="maxIdleInterval"><int value="3600000" /></field> <!-- 1 hour -->
       <field name="historyMaxSize"><int value="20" /></field>
       <field name="maxLockTime"><int value="600000" /></field> <!-- 10 minutes -->
       <field name="lockMonitorInterval"><int value="60000" /></field> <!-- 1 minute -->
       <field name="lockBufferTime"><int value="5000" /></field> <!-- 5 seconds -->
       </bean>


      The job executor is instantiated by a Spring listener :
      <!-- Bean responsible for starting and stopping the JBPM JobExecutor -->
       <bean id="jbpmLifeCycleListener"
       class="com.acme.jbpm.helpers.JbpmLifeCycleListener"
       init-method="start" destroy-method="stop">
       <property name="configuration" value="classpath:jbpm.cfg.xml" />
       <property name="sessionFactory" ref="jbpmSessionFactory" />
       </bean>


      3- Create a timer :
      public static void createNotificationTimer(ExecutionContext context,
       Date dueDate, String timerName, String nodeName) {
      
       try {
       // getting data from the context
       long processId = context.getProcessInstance().getId();
       Token token = context.getToken();
       String orderOrigin = (String) context
       .getVariable(ContextVariable.orderOrigin);
       String externalOrderId = (String) context
       .getVariable(ContextVariable.externalOrderId);
       Node myNode = context.getProcessDefinition().getNode(nodeName);
      
       // creating the action
       Action timedAction = new Action();
       Delegation timedDelegation = new Delegation(
       "com.acme.businesslayer.jbpm.timers.NotificationAction");
       timedDelegation
       .setConfiguration(String
       .format("<tokenId>%d</tokenId><externalOrderId>%s</externalOrderId><orderOrigin>%s</orderOrigin>",
       token.getId(), externalOrderId, orderOrigin));
       timedAction.setActionDelegation(timedDelegation);
      
       // creating the timer
       Timer timer = new Timer(token);
       String completeTimerName = String.format("%s-%d", timerName,
       processId);
       timer.setName(completeTimerName);
       timer.setAction(timedAction);
       timer.setDueDate(dueDate);
      
       // setting the execution context
       context.setTimer(timer);
      
       // scheduling the timer
       myNode.fireEvent("timer-create", context);
       JbpmConfiguration conf = (JbpmConfiguration) SpringHelper
       .getBean("jbpmConfiguration");
       JbpmContext myContext = conf.createJbpmContext();
       myContext.setSessionFactory((SessionFactory) SpringHelper
       .getBean("jbpmSessionFactory"));
       SchedulerService schedulerService = (SchedulerService) myContext.getServices().getService(Services.SERVICENAME_SCHEDULER);
       SchedulerService.createTimer(timer);
       myContext.close();
      
       } catch (Exception e) {
       e.printStackTrace();
       }
       }


      4- Cancel a timer :

      public static void cancelTimer(String timerName, Token token) {
       JbpmConfiguration conf = (JbpmConfiguration) SpringHelper
       .getBean("jbpmConfiguration");
       JbpmContext testContext = conf.createJbpmContext();
       myContext.setSessionFactory((SessionFactory) SpringHelper
       .getBean("jbpmSessionFactory"));
      
       SchedulerService schedulerService = (SchedulerService) myContext.getServices().getService(Services.SERVICENAME_SCHEDULER);
       String completeTimerName = String.format("%s-%d", timerName, token.getProcessInstance().getId());
       schedulerService.deleteTimersByName(completeTimerName, token);
       myContext.close();
       }
      


      Hope this will help save time for some of you.



        • 1. Re: [HOW-TO] Programmatically create and cancel Timers
          dejan

          Hi Fabian,
          could you also paste the code from JbpmLifeCycleListener class?

          Thanks,
          Dejan

          • 2. Re: [HOW-TO] Programmatically create and cancel Timers
            sonicfab

            Ok here it is below.
            (Maybe I should start a blog ;-), or independent paid consultancy ;-)) )

            public class JbpmLifeCycleListener {
            
             /** Keylogger. */
             private static KeyLogger keyLogger = KeyLoggerFactory.getLogger(JbpmLifeCycleListener.class);
            
             /** Jbpm configuration */
             private JbpmConfiguration _jbpmConfiguration;
            
             /** Resource. */
             private Resource configuration;
            
             /** SessionFactory */
             private SessionFactory sessionFactory;
            
             /** Set the configuration file resource. */
             @Required
             public void setConfiguration(Resource configuration) {
             this.configuration = configuration;
             }
            
             /** Set the hibernate session factory. */
             @Required
             public void setSessionFactory(SessionFactory sessionFactory) {
             this.sessionFactory = sessionFactory;
             }
            
             /**
             * Performs work after creation of JbpmConfiguration.
             */
             public void start() {
             initJBPMConfiguration();
             if (null != _jbpmConfiguration) {
             afterCreation(_jbpmConfiguration);
             }
             }
            
             /**
             * Initialize the {@link JbpmConfiguration}
             *
             */
             public void initJBPMConfiguration() {
             if (null == _jbpmConfiguration) {
             try {
             _jbpmConfiguration = JbpmConfiguration.parseInputStream(configuration.getInputStream());
             JbpmContext jbpmContext = _jbpmConfiguration.createJbpmContext();
             ServiceFactory svF = _jbpmConfiguration.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
            
             // Configure it to start its own transaction and open hibernate session
             DbPersistenceServiceFactory dbF = (DbPersistenceServiceFactory)svF;
             dbF.setTransactionEnabled(true);
             dbF.setCurrentSessionEnabled(false);
             try {
             jbpmContext.setSessionFactory(sessionFactory);
             }
            
             finally {
             if (null != jbpmContext) jbpmContext.close();
             }
             } catch (IOException e) {
             keyLogger.log(DefaultLogKeyMessageConstants.GENERIC_ERROR_MESSAGE, new String[]{"Unable" +
             "to retrieve JBPMConfiguration"});
             }
             }
            
             }
            
             /**
             * Performs work before destruction JbpmConfiguration.
             */
             public void stop() {
             initJBPMConfiguration();
             if (null != _jbpmConfiguration) {
             beforeDestroy(_jbpmConfiguration);
             }
             }
            
             /**
             * Called after creation of the jbpm configuration to perform additional tasks.
             * @param configuration jbpmConfiguration
             */
             public void afterCreation(JbpmConfiguration configuration) {
             keyLogger.debug("Starting job executor...");
             configuration.startJobExecutor();
             keyLogger.debug("Job executor started.");
             }
            
             /**
             * Called before destruction of the jbpm configuration.
             * @param configuration
             */
             public void beforeDestroy(JbpmConfiguration configuration) {
             keyLogger.debug("Stopping job executor...");
             configuration.getJobExecutor().stop();
             keyLogger.debug("Job executor stopped.");
             }
            
            }


            • 3. Re: [HOW-TO] Programmatically create and cancel Timers
              dejan

              Thanks.
              However, I already found another solution that better suited my needs. http://www.jboss.com/index.html?module=bb&op=viewtopic&t=119652
              Anyway, I am sure your code will help other people. I know that I had hard time trying to configure Jbpm executor with Spring.

              • 4. Re: [HOW-TO] Programmatically create and cancel Timers
                kukeltje

                There is a jBPM wiki where you can add these kinds of things... feel free