jbpm4 timer 定时器配置
jbpm的定时器支持嵌入到状态节点(State),任务节点(Task),子流程(Sub-process),组(Group),流转线(Transition),自定义节点(Custom)等元素中,下面是我近段时间做限时审批流程时对jbpm的一些理解和用法做一下记录。
当进入配置定时器元素时,定时器被创建,当流程一直处于这个活动时候,定时器可以触发,直到到到截止时间(duedate),当流程离开活动,定时器就会被取消。
timer的属性:
持续时间表达式包含下列语法:
[<Base Date> {+|-}] quantity [business] {second | seconds | minute | minutes | hour | hours | day | days | week | weeks | month | months | year | years}
这里的 Base Date 是一个 EL。 quantity 是一个正整数。 添加额外的 business 意味着 只有工作时间应该被计算在持续时间内。 如果没有指定 business,持续时间会使用绝对时间间隔。注意:'business'还不支持对 base date 进行减法运算!
下面是一些jbpm开发文档中的简单的例子:
下面的例子用法都是可行的
<timer name="daysBeforeHoliday" duedate="5 business days">...</timer>
<timer name="pensionDate" duedate="#{dateOfBirth} + 65 years" >...</timer>
<timer name="pensionReminder" duedate="#{dateOfPension} - 1 year" >...</timer>
<timer name="fireWorks" duedate="#{chineseNewYear} repeat="1 year" >...</timer>
<reminder name="hitBoss" duedate="#{payRaiseDay} + 3 days" repeat="1 week" />
<reminder name="hitBoss" duedate="#{payRaiseDay} + 3 days" repeat="#{iritationFactor}"
/>
但是,下面的例子,在'business'的结合运算中使用减法,是不被支持的,会抛出一个异常,会导致持续时间变成一个过去的事件。
<reminder name="toGoOrNotToGo" duedate="#{goLive} - 3 business days"/>
要想定时器起作用,必须修改jbpm.cfg.xml文件,将预先注释掉的<import resource="jbpm.jobexecutor.cfg.xml" />去掉注释。
jbpm4.x中带的jbpm.jobexecutor.cfg.xml的内容是没有详细配置的,但是,它会执行默认的配置。
原始的配置文件内容是:
<?xml version="1.0" encoding="UTF-8"?><jbpm-configuration> <process-engine-context> </process-engine-context></jbpm-configuration>
<?xml version="1.0" encoding="UTF-8"?><jbpm-configuration> <process-engine-context> <job-executor threads="4" idle="30000" idle-max="60000" lock="3600000" /> </process-engine-context></jbpm-configuration>
<?xml version="1.0" encoding="UTF-8"?><process name="TimerTransitionTest" xmlns="http://jbpm.org/4.4/jpdl"><start g="19,50,48,48"><transition to="guardedWait" /></start><state g="98,46,127,52" name="guardedWait"><transition name="timeout" to="escalation" g="-49,-22"><timer duedate="10 minutes" /></transition><transition g="-16,-17" name="go on" to="next step" /></state><state g="287,52,83,53" name="next step" /><state name="escalation" g="122,174,80,40" /></process>
package com.lujinyong.timer.transition;import static org.junit.Assert.assertEquals;import static org.junit.Assert.assertTrue;import java.util.ArrayList;import java.util.Collections;import java.util.List;import java.util.Set;import org.jbpm.api.Configuration;import org.jbpm.api.Execution;import org.jbpm.api.ExecutionService;import org.jbpm.api.ManagementService;import org.jbpm.api.ProcessEngine;import org.jbpm.api.ProcessInstance;import org.jbpm.api.job.Job;import org.junit.Test;public class TestTimer {/** * * @Description: 部署流程 * @Auther: lujinyong * @Date: 2013-6-24 下午03:41:01 */@Testpublic void testDeploy1() {// 1.get processEngineProcessEngine processEngine = Configuration.getProcessEngine();processEngine.getRepositoryService().createDeployment().addResourceFromClasspath("com/lujinyong/timer/transition/TimerTransitionTest.jpdl.xml").addResourceFromClasspath("com/lujinyong/timer/transition/TimerTransitionTest.png").deploy();}/** * * @Description: 测试超时的情况,流向escalation * @Auther: lujinyong * @Date: 2013-6-24 下午05:38:35 */@Testpublic void testTimerTransitionTimerFires() {ProcessEngine processEngine = Configuration.getProcessEngine();ExecutionService executionService = processEngine.getExecutionService();ManagementService managementService = processEngine.getManagementService(); ProcessInstance processInstance = executionService.startProcessInstanceByKey("TimerTransitionTest"); //查询定时器 Job job = managementService.createJobQuery() .processInstanceId(processInstance.getId()) .uniqueResult(); //假设定时器被触发了,通过编码执行定时器进行模拟 managementService.executeJob(job.getId()); processInstance = executionService.findProcessInstanceById(processInstance.getId()); Set<String> expectedActivityNames = Collections.singleton("guardedWait"); assertEquals(expectedActivityNames, processInstance.findActiveActivityNames()); assertEquals(Boolean.TRUE, executionService.getVariable(processInstance.getId(), "escalation")); }/** * * @Description: 测试未超时的情况,流向next step * @Auther: lujinyong * @Date: 2013-6-24 下午05:39:45 */@Testpublic void testTimerTransitionContinueBeforeTimerFires() {ProcessEngine processEngine = Configuration.getProcessEngine();ExecutionService executionService = processEngine.getExecutionService();ManagementService managementService = processEngine.getManagementService(); ProcessInstance processInstance = executionService.startProcessInstanceByKey("TimerTransitionTest"); String executionId = processInstance.findActiveExecutionIn("guardedWait").getId(); executionService.signalExecutionById(executionId, "go on"); processInstance = executionService.findProcessInstanceById(processInstance.getId()); assertTrue(processInstance.isActive("next step")); List<Job> jobs = managementService.createJobQuery() .processInstanceId(processInstance.getId()) .list(); assertEquals(new ArrayList<Job>(), new ArrayList<Job>(jobs)); }}
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"><hibernate-configuration> <session-factory> <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/jbpm4?characterEcoding/=utf-8</property><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><property name="hibernate.connection.username">root</property><property name="hibernate.connection.password">root</property><property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property><property name="hibernate.hbm2ddl.auto">update</property><property name="hibernate.show_sql">true</property> <mapping resource="jbpm.repository.hbm.xml" /> <mapping resource="jbpm.execution.hbm.xml" /> <mapping resource="jbpm.history.hbm.xml" /> <mapping resource="jbpm.task.hbm.xml" /> <mapping resource="jbpm.identity.hbm.xml" /> </session-factory></hibernate-configuration>
package com.lujinyong.initdb;import org.hibernate.cfg.Configuration;import org.junit.Test;public class CreateDB {@Testpublic void test(){Configuration configuration = new Configuration();configuration.configure("jbpm.hibernate.cfg.xml");configuration.buildSessionFactory();}}