### Eclipse Workspace Patch 1.0
#P jbpm4
Index: modules/api/src/main/java/org/jbpm/api/job/Timer.java
===================================================================
--- modules/api/src/main/java/org/jbpm/api/job/Timer.java (revision 6403)
+++ modules/api/src/main/java/org/jbpm/api/job/Timer.java (working copy)
@@ -38,5 +38,8 @@
/** indicates the delay for repeating this timer after successful execution */
String getRepeat();
+
+ /** indicates the cron expression used for this timer*/
+ String getCronExpression();
}
\ No newline at end of file
Index: modules/jpdl/src/main/java/org/jbpm/jpdl/internal/xml/JpdlParser.java
===================================================================
--- modules/jpdl/src/main/java/org/jbpm/jpdl/internal/xml/JpdlParser.java (revision 6588)
+++ modules/jpdl/src/main/java/org/jbpm/jpdl/internal/xml/JpdlParser.java (working copy)
@@ -41,6 +41,8 @@
import org.jbpm.jpdl.internal.activity.JpdlBinding;
import org.jbpm.jpdl.internal.activity.MailListener;
import org.jbpm.jpdl.internal.model.JpdlProcessDefinition;
+import org.jbpm.pvm.internal.cal.CronExpression;
+import org.jbpm.pvm.internal.cal.Duration;
import org.jbpm.pvm.internal.el.Expression;
import org.jbpm.pvm.internal.email.impl.MailProducerImpl;
import org.jbpm.pvm.internal.email.impl.MailTemplate;
@@ -375,7 +377,14 @@
String duedatetime = XmlUtil.attribute(timerElement, "duedatetime");
if (duedate != null) {
- timerDefinition.setDueDateDescription(duedate);
+ if (Duration.isValidExpression(duedate)) {
+ timerDefinition.setDueDateDescription(duedate);
+ } else if (CronExpression.isValidExpression(duedate)) {
+ timerDefinition.setCronExpression(duedate);
+ }else {
+ timerDefinition.setDueDateDescription(duedate);
+ }
+
}
else if (duedatetime != null) {
String dueDateTimeFormatText =
Index: modules/test-db/src/test/java/org/jbpm/test/timer/TimerCrontabTest.java
===================================================================
--- modules/test-db/src/test/java/org/jbpm/test/timer/TimerCrontabTest.java (revision 0)
+++ modules/test-db/src/test/java/org/jbpm/test/timer/TimerCrontabTest.java (revision 0)
@@ -0,0 +1,221 @@
+package org.jbpm.test.timer;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+
+import org.jbpm.api.ProcessInstance;
+import org.jbpm.api.job.Job;
+import org.jbpm.api.job.Timer;
+import org.jbpm.api.listener.EventListener;
+import org.jbpm.api.listener.EventListenerExecution;
+import org.jbpm.test.JbpmTestCase;
+
+
+public class TimerCrontabTest extends JbpmTestCase {
+
+ /*
+ * Uncomment this to test with job executor being active
+ public void testTimerCrontabWithJobExecutor() {
+
+ int currentHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
+
+ deployJpdlXmlString(
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ "");
+
+
+ HashMap vars = new HashMap();
+ vars.put("index", 0);
+
+ ProcessInstance pi = executionService.startProcessInstanceByKey("TimerCrontab", vars);
+
+ try {
+ Thread.sleep(120000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ pi = executionService.findProcessInstanceById(pi.getId());
+ String executionId = pi.findActiveExecutionIn("state1").getId();
+ executionService.signalExecutionById(executionId);
+ }
+ */
+
+ public void testTransitionTimerCrontab() {
+
+ Calendar cl = Calendar.getInstance();
+ int currentHour = cl.get(Calendar.HOUR_OF_DAY);
+ cl.add(Calendar.MINUTE, 1);
+ cl.set(Calendar.SECOND, 0);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+
+ deployJpdlXmlString(
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ "");
+
+
+ HashMap vars = new HashMap();
+ vars.put("index", 0);
+
+ ProcessInstance pi = executionService.startProcessInstanceByKey("TimerCrontab", vars);
+
+ List jobs = managementService.createJobQuery().timers().list();
+ assertEquals(1, jobs.size());
+ assertEquals("0 * "+ currentHour +" * * ?", ((Timer) jobs.get(0)).getCronExpression());
+
+ assertEquals(sdf.format(cl.getTime()), sdf.format(((Timer) jobs.get(0)).getDueDate()));
+
+
+ managementService.executeJob(jobs.get(0).getId());
+
+ jobs = managementService.createJobQuery().timers().list();
+ assertEquals(1, jobs.size());
+
+ assertEquals(sdf.format(cl.getTime()), sdf.format(((Timer) jobs.get(0)).getDueDate()));
+
+ managementService.executeJob(jobs.get(0).getId());
+
+ jobs = managementService.createJobQuery().timers().list();
+ assertEquals(1, jobs.size());
+
+ assertEquals(sdf.format(cl.getTime()), sdf.format(((Timer) jobs.get(0)).getDueDate()));
+
+ managementService.executeJob(jobs.get(0).getId());
+
+ assertProcessInstanceEnded(pi);
+
+ pi = executionService.findProcessInstanceById(pi.getId());
+ assertNull(pi);
+ }
+
+ public void testEventTimerCrontab() {
+
+ Calendar cl = Calendar.getInstance();
+ int currentHour = cl.get(Calendar.HOUR_OF_DAY);
+ cl.add(Calendar.MINUTE, 1);
+ cl.set(Calendar.SECOND, 0);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+
+ deployJpdlXmlString(
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ "");
+
+
+ HashMap vars = new HashMap();
+ vars.put("index", 0);
+
+ ProcessInstance pi = executionService.startProcessInstanceByKey("TimerCrontab", vars);
+
+ List jobs = managementService.createJobQuery().timers().list();
+ assertEquals(1, jobs.size());
+ assertEquals("0 * "+ currentHour +" * * ?", ((Timer) jobs.get(0)).getCronExpression());
+
+ assertEquals(sdf.format(cl.getTime()), sdf.format(((Timer) jobs.get(0)).getDueDate()));
+
+
+ managementService.executeJob(jobs.get(0).getId());
+
+ jobs = managementService.createJobQuery().timers().list();
+ assertEquals(1, jobs.size());
+
+ assertEquals(sdf.format(cl.getTime()), sdf.format(((Timer) jobs.get(0)).getDueDate()));
+
+ managementService.executeJob(jobs.get(0).getId());
+
+ jobs = managementService.createJobQuery().timers().list();
+ assertEquals(1, jobs.size());
+
+ assertEquals(sdf.format(cl.getTime()), sdf.format(((Timer) jobs.get(0)).getDueDate()));
+
+ managementService.executeJob(jobs.get(0).getId());
+
+ pi = executionService.findProcessInstanceById(pi.getId());
+ String executionId = pi.findActiveExecutionIn("state1").getId();
+ executionService.signalExecutionById(executionId);
+
+ assertProcessInstanceEnded(pi);
+
+ pi = executionService.findProcessInstanceById(pi.getId());
+ assertNull(pi);
+
+ }
+
+
+ public static class Listener implements EventListener {
+
+ private static final long serialVersionUID = 1L;
+
+ public void notify(EventListenerExecution execution) throws Exception {
+ Integer index = (Integer) execution.getVariable("index");
+
+ index++;
+ execution.setVariable("index", index);
+ }
+
+}
+}
+
Property changes on: modules\test-db\src\test\java\org\jbpm\test\timer\TimerCrontabTest.java
___________________________________________________________________
Added: svn:keywords
+ Id Revision
Added: svn:eol-style
+ LF
Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/model/TimerDefinitionImpl.java
===================================================================
--- modules/pvm/src/main/java/org/jbpm/pvm/internal/model/TimerDefinitionImpl.java (revision 6403)
+++ modules/pvm/src/main/java/org/jbpm/pvm/internal/model/TimerDefinitionImpl.java (working copy)
@@ -53,7 +53,7 @@
return repeat;
}
public void setRepeat(String repeat) {
- if (cronExpression != null) {
+ if (cronExpression != null && repeat != null) {
throw new JbpmException("Can't use 'repeat' and 'cronExpression' together for same timer");
}
this.repeat = repeat;
Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/model/ScopeInstanceImpl.java
===================================================================
--- modules/pvm/src/main/java/org/jbpm/pvm/internal/model/ScopeInstanceImpl.java (revision 6479)
+++ modules/pvm/src/main/java/org/jbpm/pvm/internal/model/ScopeInstanceImpl.java (working copy)
@@ -305,7 +305,10 @@
if (timer.getDueDate() == null && timerDefinition.getCronExpression() != null) {
try {
- timer.setDueDate(new CronExpression(timerDefinition.getCronExpression()).getNextValidTimeAfter(Clock.getTime()));
+ CronExpression cronExpr = new CronExpression(timerDefinition.getCronExpression());
+ timer.setDueDate(cronExpr.getNextValidTimeAfter(Clock.getTime()));
+ timer.setCronExpression(cronExpr.getCronExpressionString());
+
} catch (ParseException pe) {
throw new JbpmException("Can't parse cron expression " + timerDefinition.getCronExpression(), pe);
}
Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/job/TimerImpl.java
===================================================================
--- modules/pvm/src/main/java/org/jbpm/pvm/internal/job/TimerImpl.java (revision 6556)
+++ modules/pvm/src/main/java/org/jbpm/pvm/internal/job/TimerImpl.java (working copy)
@@ -28,6 +28,7 @@
import org.jbpm.api.cmd.Environment;
import org.jbpm.api.job.Timer;
import org.jbpm.internal.log.Log;
+import org.jbpm.pvm.internal.cal.CronExpression;
import org.jbpm.pvm.internal.cal.Duration;
import org.jbpm.pvm.internal.env.EnvironmentImpl;
import org.jbpm.pvm.internal.id.DbidGenerator;
@@ -57,7 +58,9 @@
protected String signalName;
protected String eventName;
protected String repeat;
+ protected String cronExpression;
+
public static final String EVENT_TIMER = "timer";
public TimerImpl() {
@@ -100,17 +103,28 @@
}
// if there is no repeat on this timer
- if (repeat == null) {
+ // nor cron expression is used
+ // or execution is ended meaning that it was signaled to continue
+ if (repeat==null && cronExpression == null || (execution.isEnded())) {
+
// have the timer deleted
return true;
}
// suppose that it took the timer runner thread a very long time to execute the timers
// then the repeat action duedate could already have passed
- do {
- setDueDateDescription(repeat);
- } while (dueDate.getTime() <= Clock.getTime().getTime());
+ if (repeat != null) {
+ do {
+ setDueDateDescription(repeat);
+ } while (dueDate.getTime() <= Clock.getTime().getTime());
+ } else if (cronExpression != null) {
+
+ do {
+ this.setDueDate(new CronExpression(cronExpression).getNextValidTimeAfter(new Date(Clock.getTime().getTime()+3600)));
+ } while (dueDate.getTime() <= Clock.getTime().getTime());
+ }
+
if (log.isDebugEnabled())
log.debug("rescheduled " + this + " for " + formatDueDate(dueDate));
@@ -184,4 +198,10 @@
public void setRepeat(String repeat) {
this.repeat = repeat;
}
+ public String getCronExpression() {
+ return cronExpression;
+ }
+ public void setCronExpression(String cronExpression) {
+ this.cronExpression = cronExpression;
+ }
}
Index: modules/pvm/src/main/resources/jbpm.execution.hbm.xml
===================================================================
--- modules/pvm/src/main/resources/jbpm.execution.hbm.xml (revision 6635)
+++ modules/pvm/src/main/resources/jbpm.execution.hbm.xml (working copy)
@@ -248,6 +248,7 @@
+