整体来说实现的非常清晰:  
1、引擎解析流程定义xml时,给相应的事件挂接上create-timer 和 cancel-timer动作  
2、流程实例实际运转时,create-timer动作在相应事件触发时执行  
3、create-timer在job表里插入相应时间job记录,给该job记录附上计算完毕的执行时间  
4、JobExecutorServlet在后台启动一到多个JobExecutorThread线程  
5、JobExecutorThread线程不停的每隔一段时间对job表扫描一次,找出需要执行的job记录,执行之  
6、只执行一次的job记录,执行完毕后删除之;重复执行的job记录,写入新的执行时间,更新之  
7、相应事件触发cancel-timer动作,将对应job记录从job表里删除
  下面具体用代码来说话(挂接到node节点):  
1、引擎解析流程定义xml  
  JpdlXmlReader.java 
  protected void readNodeTimer(Element timerElement, Node node) {
    String name = timerElement.attributeValue("name", node.getName());
   
    CreateTimerAction createTimerAction = new CreateTimerAction();
    createTimerAction.read(timerElement, this);
    createTimerAction.setTimerName(name);
    createTimerAction.setTimerAction(readSingleAction(timerElement));
    addAction(node, Event.EVENTTYPE_NODE_ENTER, createTimerAction);
   
    CancelTimerAction cancelTimerAction = new CancelTimerAction();
    cancelTimerAction.setTimerName(name);
    addAction(node, Event.EVENTTYPE_NODE_LEAVE, cancelTimerAction);
  }
  可以看到,引擎把xml中timer节点解析成了两个ACTION:CreateTimerAction和CancelTimerAction
  CreateTimerAction会在进入该节点时触发,而CancelTimerAction会在令牌离开该节点时触发。  
2、看看CreateTimerAction和CancelTimerAction究竟在做些什么
  CreateTimerAction.java
   public void execute(ExecutionContext executionContext) throws Exception {
    Timer timer = createTimer(executionContext);
    SchedulerService schedulerService = (SchedulerService) Services.getCurrentService(Services.SERVICENAME_SCHEDULER);
    schedulerService.createTimer(timer);
  }
  很明显,是通过一个职责集中的schedulerService向job表中插入了一条job记录,注意到这个方法:
  protected Timer createTimer(ExecutionContext executionContext) {
    Timer timer = new Timer(executionContext.getToken());
    
.
    if (dueDate!=null) {
      Duration duration = new Duration(dueDate);
      Date dueDateDate = businessCalendar.add( new Date(), duration );
      timer.setDueDate(dueDateDate);
    }
    
.
   
    return timer;
  } 
  这里利用JBPM提供的工作时间计算组件计算了job的执行时间。
  CancelTimerAction就很简单了,删除相应的job记录。
  CancelTimerAction.java
  public void execute(ExecutionContext executionContext) throws Exception {
    SchedulerService schedulerService = (SchedulerService) Services.getCurrentService(Services.SERVICENAME_SCHEDULER);
    schedulerService.deleteTimersByName(timerName, executionContext.getToken());
  }
  3、JobExecutorServlet是干什么的
  启动线程
  public void init() throws ServletException {
    
.
    jbpmConfiguration.startJobExecutor();
  } 
  4、线程是如何工作
  public void run() {
    try {
      currentIdleInterval = idleInterval;
      while (isActive) {
        try {
          Collection acquiredJobs = acquireJobs();   //从job表里获得将要执行的job记录
          if (! acquiredJobs.isEmpty()) {    //如果记录不为空,则开始执行
            Iterator iter = acquiredJobs.iterator();
            while (iter.hasNext() && isActive) {
              Job job = (Job) iter.next();
              executeJob(job);             //执行
            }
          } else { // no jobs acquired     //如果没有可执行的job,则等待一段时间
            if (isActive) {
              long waitPeriod = getWaitPeriod();  //等待的时间是找出即将执行的job离现在最近的时间间隔
              if (waitPeriod>0) {
                synchronized(jobExecutor) {
                  jobExecutor.wait(waitPeriod);
                }
              }
            }
          }
         
         
.
    } catch (Throwable t) {
      t.printStackTrace();
    } finally {
      log.info(getName()+" leaves cyberspace");
    }
  } 
  看看实际执行的方法
  protected void executeJob(Job job) {
    JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
    try {
      JobSession jobSession = jbpmContext.getJobSession();
      job = jobSession.loadJob(job.getId());
      try {
        log.debug("executing job "+job);
        if (job.execute(jbpmContext)) {    //交由Job对象本身去完成执行的逻辑,并决定是否删除job记录
          jobSession.deleteJob(job);
        }
            
.
  } 
  5、着重关注Time对象
  在上面我们看到实际执行的代码是job.execute(jbpmContext);
  Time 是Job的子类,看看它的实现:
  public boolean execute(JbpmContext jbpmContext) throws Exception {
    boolean deleteThisJob = true;       //执行完毕后是否删除job记录
    ExecutionContext executionContext = new ExecutionContext(token);
    executionContext.setTimer(this);
    if (taskInstance!=null) {
      executionContext.setTaskInstance(taskInstance);
    }
    // 触发timer事件
    if (graphElement!=null) {
      graphElement.fireAndPropagateEvent(Event.EVENTTYPE_TIMER, executionContext);
    }
    // 如果timer节点上挂有action则执行之
    if (action!=null) {
      try {
        log.debug("executing timer '"+this+"'");
        action.execute(executionContext);
      } catch (Exception actionException) {
      
.
        }
    // 如果定义了transition属性,则流程顺着定义的路径流转
    if ( (transitionName!=null)
         && (exception==null) // and if no unhandled exception occurred during the action 
       ) {
      if (token.getNode().hasLeavingTransition(transitionName)) {
        token.signal(transitionName);
      }
    }
   
    // 如果定义了repeat属性则job记录不容许删除,同时计算新的执行时间
    if (repeat!=null) {
      deleteThisJob = false;
      while (dueDate.getTime()<=System.currentTimeMillis()) {
        dueDate = businessCalendar
              .add(dueDate,
                new Duration(repeat));
      }
      log.debug("updated timer for repetition '"+this+"' in '"+(dueDate.getTime()-System.currentTimeMillis())+"' millis");
    }
   
    return deleteThisJob;
  } 
http://www.blogjava.net/ronghao 荣浩原创,转载请注明出处:)
	
posted on 2007-06-22 17:13 
ronghao 阅读(1961) 
评论(0)  编辑  收藏  所属分类: 
工作流jbpm3