[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.