1 Reply Latest reply on Jan 13, 2014 1:58 AM by swiderski.maciej

    TimerManager.ProcessJob.execute method

    zhangjing2000

      We 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());

                      }

                  }

              }

        • 1. Re: TimerManager.ProcessJob.execute method
          swiderski.maciej

          what you mean process instance info was deleted from data base? Was it deleted manually from data base or via API? If it was deleted from db manually that is mainly the problem. Please take into consideration that other parts might be left not cleaned as well - any data stored by the process instance in working memory (as facts) including process instance itself which then will result in the same issue as with timers - will be in session but not actually available as process instance.

           

          Anyway feel free to file jira issue for it and pull requests is always welcome too.

           

          HTH