以前开始接触jbpm的时候,也曾经发表了一篇关于调度的文章http://blog.csdn.net/jeffen2006/archive/2006/10/20/1342167.aspx,其中有很多不甚了解的东东,这几天又研究了一下,共享给各位学友。
本系列仅从应用的角度出发进行介绍:
jbpm的调度部分只要分为2块,timer主要是流程设计人员的工作,将timer放置到流程中;scheduler是jbpm自己维护的,我们只需要在后台进行调用即可。
根据吃甘蔗的方法,我们先说相对容易一点的scheduler。我们可以认为scheduler就是一个后台线程在不停的监听着timer(jbpm_timer表),如果有需要触发的timer生成了,就按照timer的属性定时或者循环触发它。
jbpm提供了2种调用scheduler的方法:
一种是用在web应用的,采用org.jbpm.scheduler.impl.SchedulerServlet,具体的方法这个类的javadoc有很好的示例,我们只需在web.xml中加载它就行了;
另一种是针对的c-s程序,jbpm提供了一个很好的示例org.jbpm.scheduler.impl.SchedulerMain,我们可以参照它编写我们自己的Scheduler。
下面我就编写一个cs程序来实现Scheduler,并调用一个最简单的timer。
这个timer从第5秒开始每隔3秒执行script中的内容。
- xml version="1.0" encoding="UTF-8"?>
- <process-definition xmlns="" name="yytest">
- <start-state name="start">
- <transition name="" to="a">transition>
- start-state>
- <state name="a">
- <timer name='reminder'
- duedate='5 seconds'
- repeat='3 seconds'
- >
- <script>System.out.println(new Date()+"----node enter:send mail to operator.");script>
- timer>
- <transition name="" to="end">transition>
- state>
- <end-state name="end">end-state>
- process-definition>
下面的程序看注释就很清楚了:
- package com.jeffentest;
- import org.jbpm.*;
- import org.jbpm.graph.def.ProcessDefinition;
- import org.jbpm.graph.exe.*;
- import org.jbpm.scheduler.impl.Scheduler;
- public class Jeffentest {
- static JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
- static ProcessDefinition processDefinition = null;
- static ProcessInstance processInstance = null;
- static Scheduler scheduler = null;
- public static void initSchedular() {//设置Schedular的属性
- scheduler = new Scheduler();
- int interval = 5000;
- scheduler.setInterval(interval);
- int historyMaxSize = 0;
- scheduler.setHistoryMaxSize(historyMaxSize);
- scheduler.start();
- }
- public static void destroy() {//这个例子没用到
- scheduler.stop();
- }
- static class MySchedularThread extends Thread{//实际业务处理线程
- public void run(){
- JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
- try {
- long processInstanceId =1;
- processInstance = jbpmContext.loadProcessInstance(processInstanceId);
- Token token = processInstance.getRootToken();
- System.out.println(token.getNode());
- //一定要运行到有timer生成,触发
- token.signal();
- System.out.println(token.getNode());
- jbpmContext.save(processInstance);
- //如果这里程序到这里退出的话可以看到jbpm_timer表里有一条数据
- Thread.sleep(30*1000);//为模拟效果,此线程停止30秒
- //节点跳过,timer结束,jbpm_timer表该数据清空
- token.signal();
- System.out.println(token.getNode());
- jbpmContext.save(processInstance);
- }catch(Exception e){
- e.printStackTrace();
- }finally {
- jbpmContext.close();
- }
- }
- }
- public static void main(String[] args) {
- initSchedular ();
- MySchedularThread mst=new MySchedularThread();
- mst.start();
- }
- }
运行结果:
StartState(start)
State(a)
Thu Dec 07 13:17:11 CST 2006----node enter:send mail to operator.
Thu Dec 07 13:17:16 CST 2006----node enter:send mail to operator.
Thu Dec 07 13:17:21 CST 2006----node enter:send mail to operator.
Thu Dec 07 13:17:26 CST 2006----node enter:send mail to operator.
Thu Dec 07 13:17:31 CST 2006----node enter:send mail to operator.
EndState(end)
scheduler就先说这么多了,至于timer等我下篇吧,等下要去参加jbuilder2007的深圳发布会。
上篇介绍了通过跳过节点可以终止timer,其实也可以直接在流程定义里设置timer的终止,就是使用cancel-timer元素。
- <?xml version="1.0" encoding="UTF-8"?>
- <process-definition xmlns="" name="yytest">
- <start-state name="start">
- <transition name="" to="a"></transition>
- </start-state>
- <state name='a'>
- <timer name='reminder'
- duedate='0 seconds'
- repeat='3 seconds'>
- <script>System.out.println(new Date()+"----node enter:send mail to operator.");</script>
- </timer>
- <timer name='reminderend'
- duedate='12 seconds'
- transition='toend'
- >
- <script>System.out.println(new Date()+"----canceled timer");</script>
- <cancel-timer name='reminder'/>
- </timer>
- <transition name="toend" to="end"></transition>
- </state>
- <end-state name="end"></end-state>
- </process-definition>
reminderend 这个定时器,在12秒后调用cancel-timer终止定时器reminder,同时按照指定的transition结束流程。
- package com.jeffentest;
- import org.jbpm.*;
- import org.jbpm.graph.def.ProcessDefinition;
- import org.jbpm.graph.exe.*;
- import org.jbpm.scheduler.impl.Scheduler;
- public class Jeffentest {
- static JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
- static ProcessDefinition processDefinition = null;
- static ProcessInstance processInstance = null;
- static Scheduler scheduler = null;
- public static void initSchedular() {//设置Schedular的属性
- scheduler = new Scheduler();
- int interval = 5000;
- scheduler.setInterval(interval);
- int historyMaxSize = 0;
- scheduler.setHistoryMaxSize(historyMaxSize);
- scheduler.start();
- }
- public static void destroy() {//这个例子没用到
- scheduler.stop();
- }
- static class MySchedularThread extends Thread{//实际业务处理线程
- public void run(){
- JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
- try {
- long processInstanceId =1;
- processInstance = jbpmContext.loadProcessInstance(processInstanceId);
- Token token = processInstance.getRootToken();
- System.out.println(token.getNode());
- //一定要运行到有timer生成,触发<timer name='reminder'>
- token.signal();
- System.out.println(token.getNode());
- jbpmContext.save(processInstance);
- //jbpm_timer表里数据被清空、同时可以看jbpm_processinstance.end_,该流程实例也结束了
- }catch(Exception e){
- e.printStackTrace();
- }finally {
- jbpmContext.close();
- }
- }
- }
- public static void main(String[] args) {
- initSchedular ();
- MySchedularThread mst=new MySchedularThread();
- mst.start();
- }
- }
运行结果:
StartState(start)
State(a)
Fri Dec 08 10:22:26 CST 2006----node enter:send mail to operator.
Fri Dec 08 10:22:31 CST 2006----node enter:send mail to operator.
Fri Dec 08 10:22:33 CST 2006----node enter:send mail to operator.
Fri Dec 08 10:22:33 CST 2006----canceled timer
说明一下,我的这两个例子都是基于state的,如果采用node则不会给timer运行的机会。
timer还有几个特殊属性是针对task节点的,见下篇吧。
timer如果在task中,有一个属性cancel-event,可以指定那些事件可以终止timer的执行,默认是task-end,也可以指定多个事件如: 。
下面举一个默认为task-end的例子:
- xml version="1.0" encoding="UTF-8"?>
- <process-definition xmlns="" name="yytest">
- <start-state name="start">
- <transition name="" to="a">transition>
- start-state>
- <task-node name='a'>
- <task name='reminder'>
- <timer name='reminder' duedate='5 seconds' repeat='3 seconds'
- >
- <script>System.out.println(new Date()+"----node enter:send mail to operator.");script>
- timer>
- task>
- <transition name="" to="end">transition>
- task-node>
- <end-state name="end">end-state>
- process-definition>
- package com.jeffentest;
- import org.jbpm.*;
- import org.jbpm.graph.def.ProcessDefinition;
- import org.jbpm.graph.exe.*;
- import org.jbpm.scheduler.impl.Scheduler;
- public class Jeffentest {
- static JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
- static ProcessDefinition processDefinition = null;
- static ProcessInstance processInstance = null;
- static Scheduler scheduler = null;
- public static void initSchedular() {//设置Schedular的属性
- scheduler = new Scheduler();
- int interval = 5000;
- scheduler.setInterval(interval);
- int historyMaxSize = 0;
- scheduler.setHistoryMaxSize(historyMaxSize);
- scheduler.start();
- }
- public static void destroy() {//这个例子没用到
- scheduler.stop();
- }
- static class MySchedularThread extends Thread{//实际业务处理线程
- public void run(){
- JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
- try {
- long processInstanceId =1;
- processInstance = jbpmContext.loadProcessInstance(processInstanceId);
- Token token = processInstance.getRootToken();
- System.out.println(token.getNode());
- //一定要运行到有timer生成,触发
- token.signal();
- System.out.println(token.getNode());
- jbpmContext.save(processInstance);
- //jbpm_timer表里有一条数据。timer将永久运行下去,直到taskinstance.end()
- Thread.sleep(30*1000);//为模拟效果,此线程停止30秒
- jbpmContext.getTaskInstance(1).start();
- jbpmContext.getTaskInstance(1).end();//如果,屏蔽掉该句试试
- System.out.println(token.getNode());
- jbpmContext.save(processInstance);
- }catch(Exception e){
- e.printStackTrace();
- }finally {
- jbpmContext.close();
- }
- }
- }
- public static void main(String[] args) {
- initSchedular ();
- MySchedularThread mst=new MySchedularThread();
- mst.start();
- }
- }
运行结果如下:
StartState(start)
TaskNode(a)
Fri Dec 08 11:22:17 CST 2006----node enter:send mail to operator.
Fri Dec 08 11:22:22 CST 2006----node enter:send mail to operator.
Fri Dec 08 11:22:27 CST 2006----node enter:send mail to operator.
Fri Dec 08 11:22:32 CST 2006----node enter:send mail to operator.
Fri Dec 08 11:22:37 CST 2006----node enter:send mail to operator.
Fri Dec 08 11:22:42 CST 2006----node enter:send mail to operator.
EndState(end)
如果想要task启动的时候,timer就终止,可以这样配置
- <timer name='reminder' duedate='5 seconds' repeat='3 seconds' cancel-event='task-start'>
结果如下:
StartState(start)
TaskNode(a)
Fri Dec 08 11:35:59 CST 2006----node enter:send mail to operator.
Fri Dec 08 11:36:04 CST 2006----node enter:send mail to operator.
Fri Dec 08 11:36:09 CST 2006----node enter:send mail to operator.
Fri Dec 08 11:36:14 CST 2006----node enter:send mail to operator.
Fri Dec 08 11:36:19 CST 2006----node enter:send mail to operator.
TaskNode(a)
好了调度的应用就说这么多吧。没人了,赶紧去吃饭。