TimerManager.ProcessJob.execute method
zhangjing2000 Jan 10, 2014 5:02 PMWe ran into an issue (primary due to database corruption) about timer.
A process instance has been deleted from ProcessInstanceInfo table but its timer data is still persisted in SessionInfo table. When we reload sessionInfo, the timer triggered and we found the timer won't die. This became really annoying unless we have to delete the sessonInfo data.
We read jbpm source and found this could be avoid if there is a checking logic in execute method of TimerManager in package org.jbpm.process.instance.timer, see below.
public void execute(JobContext c) {
ProcessJobContext ctx = (ProcessJobContext) c;
Long processInstanceId = ctx.getProcessInstanceId();
InternalKnowledgeRuntime kruntime = ctx.getKnowledgeRuntime();
try {
if (processInstanceId == null) {
throw new IllegalArgumentException("Could not find process instance for timer ");
}
ctx.getTimer().setLastTriggered(
new Date(ctx.getKnowledgeRuntime().<SessionClock> getSessionClock().getCurrentTime()));
// if there is no more trigger reset period on timer so its node instance can be removed
if (ctx.getTrigger().hasNextFireTime() == null) {
ctx.getTimer().setPeriod(0);
}
// when run this statement, will throw an exception
((InternalProcessRuntime) kruntime.getProcessRuntime()).getSignalManager().signalEvent(processInstanceId, "timerTriggered", ctx.getTimer());
TimerManager tm = ((InternalProcessRuntime) ctx.getKnowledgeRuntime().getProcessRuntime()).getTimerManager();
// this code won't be executed as exception thrown above
if (ctx.getTimer().getPeriod() == 0) {
tm.getTimerMap().remove(ctx.getTimer().getId());
tm.getTimerService().removeJob(ctx.getJobHandle());
}
} catch (Throwable e) {
logger.error("Error when executing timer job", e);
WorkflowProcessInstanceImpl processInstance = (WorkflowProcessInstanceImpl) kruntime
.getProcessInstance(processInstanceId);
if (processInstance != null && ctx.getTimer().getPeriod() == 0) {
processInstance.setState(ProcessInstance.STATE_ABORTED);
}
// suggest to add this
if (processInstance == null) {
tm.getTimerMap().remove(ctx.getTimer().getId());
tm.getTimerService().removeJob(ctx.getJobHandle());
}
}
}