[HOW-TO] Programmatically create and cancel Timers
sonicfab Oct 11, 2007 9:40 AMI 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.