[转载]JBPM时间服务的实现

转载:http://blog.esac.cnic.cn/u/Neptune/archives/2007/231.html
整体来说实现的非常清晰:
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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值