Author: pascal.verdage
Date: 2008-07-18 11:41:20 -0400 (Fri, 18 Jul 2008)
New Revision: 1676
Modified:
jbpm4/pvm/trunk/modules/core/src/main/java/org/jbpm/pvm/internal/model/ExecutionImpl.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/timer/IncrementCounterWaitState.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/timer/TimerIntegrationTest.java
Log:
update some timer tests
+ use setters in ExecutionImpl instead of direct field access (problems with hibernate
proxies)
+ destroyTimers implementation
Modified:
jbpm4/pvm/trunk/modules/core/src/main/java/org/jbpm/pvm/internal/model/ExecutionImpl.java
===================================================================
---
jbpm4/pvm/trunk/modules/core/src/main/java/org/jbpm/pvm/internal/model/ExecutionImpl.java 2008-07-18
14:11:32 UTC (rev 1675)
+++
jbpm4/pvm/trunk/modules/core/src/main/java/org/jbpm/pvm/internal/model/ExecutionImpl.java 2008-07-18
15:41:20 UTC (rev 1676)
@@ -152,7 +152,7 @@
* null and is only created from the executions in case its needed. Note
* that not all executions are forced to have a name and duplicates are allowed.
* In case the {@link #executions} change, the executionsMap can be nulled or
- * also updated (but a check needs to be added wether it exists). */
+ * also updated (but a check needs to be added whether it exists). */
protected transient Map<String, OpenExecution> executionsMap = null;
// transient members
@@ -235,12 +235,12 @@
ExecutionImpl child = createExecution(scope.getName());
// copy the current state from the child execution to the parent execution
- child.node = node;
- child.transition = transition;
- child.propagation = propagation;
- child.transitionOrigin = transitionOrigin;
- child.previousTransition = previousTransition;
- child.previousNode = previousNode;
+ child.setNode(getNode());
+ child.setTransition(getTransition());
+ child.setPropagation(getPropagation());
+ child.setTransitionOrigin(getTransitionOrigin());
+ child.setPreviousTransition(getPreviousTransition());
+ child.setPreviousNode(getPreviousNode());
child.initializeVariables(scope, this);
child.initializeTimers(scope);
@@ -253,12 +253,12 @@
destroyVariables(scope, parent);
// copy the current state from the child execution to the parent execution
- parent.node = node;
- parent.transition = transition;
- parent.propagation = propagation;
- parent.transitionOrigin = transitionOrigin;
- parent.previousTransition = previousTransition;
- parent.previousNode = previousNode;
+ getParent().setNode(getNode());
+ getParent().setTransition(getTransition());
+ getParent().setPropagation(getPropagation());
+ getParent().setTransitionOrigin(getTransitionOrigin());
+ getParent().setPreviousTransition(getPreviousTransition());
+ getParent().setPreviousNode(getPreviousNode());
end();
parent.removeExecution(this);
@@ -413,12 +413,12 @@
public void take(Transition transition) {
checkLock();
- this.propagation = Propagation.EXPLICIT;
- this.transition = (TransitionImpl) transition;
+ setPropagation(Propagation.EXPLICIT);
+ setTransition((TransitionImpl) transition);
// copy the current node as the transition origin. the origin can be different from
// the transition source in case a transition is taken from an enclosing node
- this.transitionOrigin = node;
- this.previousTransition = null;
+ setTransitionOrigin(getNode());
+ setPreviousTransition(null);
performAtomicOperation(TAKE_TRANSITION);
}
@@ -463,7 +463,7 @@
public void proceed() {
checkLock();
- // in graph based processDefinition langauges we assume that a
+ // in graph based processDefinition languages we assume that a
// default transition is available
TransitionImpl defaultTransition = findDefaultTransition();
if (defaultTransition!=null) {
@@ -504,8 +504,8 @@
public void moveTo(NodeImpl destination) {
// if the parent node needs to know the previous node
if (destination.isPreviousNeeded()) {
- this.previousNode = node;
- this.previousTransition = transition;
+ setPreviousNode(getNode());
+ setPreviousTransition(getTransition());
} else {
this.previousNode = null;
this.previousTransition = null;
@@ -802,7 +802,13 @@
}
protected void destroyTimers(CompositeElementImpl scope) {
- // TODO
+ // TODO: is it correct?
+ TimerSession timerSession = Environment.getCurrent().get(TimerSession.class);
+ if (hasTimers && timers!=null && !timers.isEmpty()) {
+ for (Timer timer : timers) {
+ timerSession.cancel(timer);
+ }
+ }
}
public void createTimer(String eventName, String signalName, String dueDateDescription)
{
@@ -814,15 +820,13 @@
}
public void createTimer(String eventName, String signalName, String dueDateDescription,
Date dueDate, String repeat, Boolean isExclusive, Integer retries) {
- CompositeElementImpl compositeElement = null;
-
if ( (eventName==null)
&& (signalName==null)
) {
throw new PvmException("no event or signal specified");
}
if (log.isDebugEnabled()) {
- log.debug("creating timer on "+compositeElement);
+ log.debug("creating timer on "+this.toString());
}
// instantiate the timer
Modified:
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/timer/IncrementCounterWaitState.java
===================================================================
---
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/timer/IncrementCounterWaitState.java 2008-07-18
14:11:32 UTC (rev 1675)
+++
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/timer/IncrementCounterWaitState.java 2008-07-18
15:41:20 UTC (rev 1676)
@@ -21,32 +21,27 @@
/**
* @author Pascal Verdage
+ *
+ * static variables allows not to create the hibernate mapping
*/
public class IncrementCounterWaitState implements ExternalActivity {
private static final long serialVersionUID = 1L;
private static final Log log = Log.getLog(IncrementCounterWaitState.class.getName());
- public static final String COUNTER = "counter";
- public static final int MAX_COUNTER_VALUE = 5;
+ static final String COUNTER = "counter";
+ static final int MAX_COUNTER_VALUE = 5;
public void signal(ActivityExecution execution, String signalName, Map<String,
Object> parameters) throws Exception {
boolean continueToWait = true;
if ("increment".equals(signalName)) {
Object variable = execution.getVariable(COUNTER);
- if (variable instanceof Integer) {
- log.debug("incrementing integer counter");
- int counter = ((Integer) variable) + 1;
- execution.setVariable(COUNTER, counter);
- if (counter >= MAX_COUNTER_VALUE) {
- continueToWait = false;
- }
- } else if (variable instanceof String) {
+ if (variable instanceof String) {
log.debug("incrementing string counter");
String tmp = ((String) variable);
try {
int counter = Integer.valueOf(tmp);
counter += 1;
- execution.setVariable(COUNTER, counter);
+ execution.setVariable(COUNTER, Integer.toString(counter));
if (counter >= MAX_COUNTER_VALUE) {
continueToWait = false;
}
@@ -54,11 +49,13 @@
log.debug("string variable is not an integer");
}
} else {
- log.debug("variable is neither an integer nor a string");
+ log.debug("variable is not a string");
}
}
if (continueToWait) {
execution.waitForSignal();
+ } else {
+ execution.take("timeout");
}
}
Modified:
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/timer/TimerIntegrationTest.java
===================================================================
---
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/timer/TimerIntegrationTest.java 2008-07-18
14:11:32 UTC (rev 1675)
+++
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/timer/TimerIntegrationTest.java 2008-07-18
15:41:20 UTC (rev 1676)
@@ -14,123 +14,302 @@
package org.jbpm.pvm.timer;
import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
-import org.jbpm.pvm.test.base.JbpmTestCase;
+import org.jbpm.pvm.Execution;
+import org.jbpm.pvm.ExecutionService;
+import org.jbpm.pvm.ProcessService;
+import org.jbpm.pvm.activity.ActivityExecution;
+import org.jbpm.pvm.activity.ExternalActivity;
+import org.jbpm.pvm.env.Environment;
+import org.jbpm.pvm.internal.model.ExecutionImpl;
+import org.jbpm.pvm.internal.model.NodeImpl;
+import org.jbpm.pvm.internal.util.Clock;
+import org.jbpm.pvm.job.Job;
+import org.jbpm.pvm.job.JobTestHelper;
+import org.jbpm.pvm.job.Timer;
+import org.jbpm.pvm.model.OpenExecution;
+import org.jbpm.pvm.model.ProcessDefinition;
+import org.jbpm.pvm.model.ProcessFactory;
+import org.jbpm.pvm.session.DbSession;
+import org.jbpm.pvm.session.PvmDbSession;
+import org.jbpm.pvm.test.base.DbTestCase;
/**
* @author Pascal Verdage
*/
-public class TimerIntegrationTest extends JbpmTestCase {
+public class TimerIntegrationTest extends DbTestCase {
+ public static class WaitState implements ExternalActivity {
- protected Date getDueDate(long duration) {
+ private static final long serialVersionUID = 1L;
+
+ public void execute(ActivityExecution execution) {
+ execution.waitForSignal();
+ }
+
+ public void signal(ActivityExecution execution,
+ String signalName,
+ Map<String, Object> parameters) {
+ if (signalName!=null) {
+ execution.take(signalName);
+ }
+ }
+ }
+
+ private static Date getDueDate(long duration) {
return new Date(System.currentTimeMillis() + duration);
}
+
+ private static long twoDaysDuration = 2*24*60*60*1000;
- /*
- TODO finish after refactoring
+ private static ExecutionService getExecutionService() {
+ return Environment.getCurrent().get(ExecutionService.class);
+ }
+ private static ExecutionImpl deployAndInstanciateProcess(ProcessDefinition definition)
{
+ ProcessService processService = Environment.getCurrent().get(ProcessService.class);
+ processService.deploy(definition);
- public void testFixedDateTimer() {
- Date now = new Date();
- long twoDaysDuration = 2*24*60*60*1000;
- String processName = "fixedDateTimer";
+ Execution processInstance =
getExecutionService().startExecution(definition.getName());
- ProcessDefinition processDefinition = ProcessFactory.build(processName)
- .node("get input").initial().behaviour(WaitState.class)
- .timer(getDueDate(twoDaysDuration), "escalate")
- .transition("escalate").to("manager decision")
- .transition("submit").to("process input")
- .node("process input").behaviour(WaitState.class)
- .node("manager decision").behaviour(WaitState.class)
+ return (ExecutionImpl) processInstance;
+ }
+
+ public void testTimerDefinition() {
+ ProcessDefinition processDefinition =
ProcessFactory.build("timerDefinition")
+ .node("request").initial().behaviour(WaitState.class)
+ .transition().to("decide")
+ .node("decide").behaviour(WaitState.class)
+ .timer(getDueDate(twoDaysDuration), "timeout")
+ .transition("decision made").to("response") // first defined
transition is the default one
+ .transition("timeout").to("reassign")
+ .node("reassign").behaviour(WaitState.class)
+ .node("response").behaviour(WaitState.class)
.done();
+
+ ExecutionImpl processInstance = deployAndInstanciateProcess(processDefinition);
+ Execution execution = processInstance;
+ assertEquals("request", execution.getNodeName());
+ // first node is a wait state with no timer
+ execution = getExecutionService().signalExecution(execution.getDbid());
+ assertEquals("decide", execution.getNodeName());
+
+ assertTrue(execution instanceof OpenExecution);
+ OpenExecution openExecution = (OpenExecution) execution;
+
+ // timer are created in a child execution
+ assertFalse(openExecution.hasTimers());
+
+ assertEquals(1, openExecution.getExecutions().size());
+ OpenExecution child = openExecution.getExecutions().iterator().next();
+
+ NodeImpl node1 = (NodeImpl) openExecution.getNode();
+ NodeImpl node2 = (NodeImpl) child.getNode();
+ assertEquals(node1, node2);
+ assertEquals("decide", node1.getName());
+ assertNotNull(node1.getTimerDefinitions());
+
+ assertTrue(child.hasTimers());
+ Set<Timer> timers = child.getTimers();
+ assertEquals(1, timers.size());
+ }
+
+ private static ExecutionImpl loadExecutionFromDb(long id) {
+ return Environment.getCurrent().get(DbSession.class).get(ExecutionImpl.class, id);
+ }
+
+ public void testTimerExecution() {
+ ProcessDefinition processDefinition =
ProcessFactory.build("timerExecution")
+ .node("decide").initial().behaviour(WaitState.class)
+ .timer(getDueDate(twoDaysDuration), "timeout")
+ .transition("decision made").to("response") // first defined
transition is the default one
+ .transition("timeout").to("reassign")
+ .node("reassign").behaviour(WaitState.class)
+ .node("response").behaviour(WaitState.class)
+ .done();
+ ExecutionImpl processInstance = deployAndInstanciateProcess(processDefinition);
- ProcessService processService = TimerConfiguration.getProcessService();
- processService.deploy(processDefinition);
+ Execution execution = processInstance;
+ assertEquals("decide", execution.getNodeName());
- long twoDaysFromNow = now.getTime() + twoDaysDuration;
+ OpenExecution child = ((OpenExecution) execution).getExecutions().iterator().next();
+ assertEquals("decide", child.getNodeName());
+ Timer timer = child.getTimers().iterator().next();
- ExecutionService executionService = TimerConfiguration.getExecutionService();
- System.out.println("execution service: '"+executionService+"'
");
- Execution execution = executionService.startExecution(processDefinition.getName());
+ JobTestHelper jobTestHelper = getEnvironmentFactory().get(JobTestHelper.class);
+ child = (OpenExecution) jobTestHelper.executeTimer(timer.getDbid());
+ assertEquals(Execution.STATE_ENDED, child.getState());
- assertEquals("get input", execution.getNodeName());
+ // check that the subExecution was deleted
+ child = loadExecutionFromDb(child.getDbid());
+ assertNull(child);
+
+ // check that timers have been deleted
+ List<Job> jobs =
Environment.getCurrent().get(PvmDbSession.class).findAllJobs();
+ assertNotNull(jobs);
+ assertTrue(jobs.isEmpty());
+
+ // check that process is in the right state
+ execution = loadExecutionFromDb(processInstance.getDbid());
+ assertEquals("reassign", execution.getNodeName());
+ }
+
+ public void testCanceledTimer() {
+ ProcessDefinition processDefinition =
ProcessFactory.build("timerCanceled")
+ .node("decide").initial().behaviour(WaitState.class)
+ .timer(getDueDate(twoDaysDuration), "timeout")
+ .transition("decision made").to("response") // first defined
transition is the default one
+ .transition("timeout").to("reassign")
+ .node("reassign").behaviour(WaitState.class)
+ .node("response").behaviour(WaitState.class)
+ .done();
+
+ ExecutionImpl processInstance = deployAndInstanciateProcess(processDefinition);
+
+ Execution execution = processInstance;
+ assertEquals("decide", execution.getNodeName());
+
+ // signal child execution
+ Execution child = ((OpenExecution)execution).getExecutions().iterator().next();
+ execution = getExecutionService().signalExecution(child.getDbid());
+ assertEquals(Execution.STATE_ENDED, execution.getState());
+
+ // check that the subExecution was deleted
+ child = loadExecutionFromDb(child.getDbid());
+ assertNull(child);
- org.jbpm.pvm.job.Timer timer = activityInstance
- .getTimers()
- .iterator()
- .next();
+ // check that timers have been deleted
+ List<Job> jobs =
Environment.getCurrent().get(PvmDbSession.class).findAllJobs();
+ assertNotNull(jobs);
+ assertTrue(jobs.isEmpty());
- assertTrue(twoDaysFromNow <= timer.getDueDate().getTime());
+ // check that process is in the right state
+ execution = loadExecutionFromDb(processInstance.getDbid());
+ assertEquals("response", execution.getNodeName());
+ }
- EnvironmentFactory environmentFactory = TimerConfiguration.getEnvironmentFactory();
- JobTestHelper jobTestHelper = environmentFactory.get(JobTestHelper.class);
- execution = jobTestHelper.executeTimer(timer.getDbid());
+ public void testFixedDateTimer() {
+ Date now = new Date();
+ long twoDaysFromNow = now.getTime() + twoDaysDuration;
- assertEquals("manager decision", execution.getNode().getName());
+ ProcessDefinition processDefinition =
ProcessFactory.build("fixedDateTimer")
+ .node("decide").initial().behaviour(WaitState.class)
+ .timer(getDueDate(twoDaysDuration), "timeout")
+ .transition("decision made").to("response") // first defined
transition is the default one
+ .transition("timeout").to("reassign")
+ .node("reassign").behaviour(WaitState.class)
+ .node("response").behaviour(WaitState.class)
+ .done();
+
+ ExecutionImpl processInstance = deployAndInstanciateProcess(processDefinition);
+
+ Execution execution = processInstance;
+ OpenExecution child = ((OpenExecution) execution).getExecutions().iterator().next();
+ assertEquals("decide", child.getNodeName());
+
+ // check that timer's dueDate is good
+ Timer timer = child.getTimers().iterator().next();
+ assertTrue(twoDaysFromNow <= timer.getDueDate().getTime());
+
+ // timer execution is tested in testTimerExecution
}
-
- public void testRepeatedTimer() {
- long dayDuration = 24*60*60*1000;
- String processName = "repeatedTimer";
- ProcessDefinition processDefinition = ProcessFactory.build(processName)
- .node("get input").initial().behaviour(IncrementCounterWaitState.class)
- .variable(IncrementCounterWaitState.COUNTER, "0")
- .timer("1 day", "increment", "1 day")
- .transition("submit").to("process input")
- .node("process input").behaviour(WaitState.class)
+ public void testDueDateDescriptionTimer() {
+ Date now = new Date();
+ long twoDaysFromNow = now.getTime() + twoDaysDuration;
+
+ ProcessDefinition processDefinition =
ProcessFactory.build("dueDateDescriptionTimer")
+ .node("decide").initial().behaviour(WaitState.class)
+ .timer("2 days", "timeout")
+ .transition("decision made").to("response") // first defined
transition is the default one
+ .transition("timeout").to("reassign")
+ .node("reassign").behaviour(WaitState.class)
+ .node("response").behaviour(WaitState.class)
.done();
- ProcessService processService = TimerConfiguration.getProcessService();
- processService.deploy(processDefinition);
+ ExecutionImpl processInstance = deployAndInstanciateProcess(processDefinition);
- long minimumDueDate = Clock.getCurrentTime().getTime() + dayDuration;
+ Execution execution = processInstance;
+ OpenExecution child = ((OpenExecution) execution).getExecutions().iterator().next();
+ assertEquals("decide", child.getNodeName());
+
+ // check that timer's dueDate is good
+ Timer timer = child.getTimers().iterator().next();
+ assertTrue(twoDaysFromNow <= timer.getDueDate().getTime());
- ExecutionService executionService = TimerConfiguration.getExecutionService();
- Execution execution = executionService.startExecution(processName);
- long executionId = execution.getDbid();
+ // timer execution is tested in testTimerExecution
+ }
- EnvironmentFactory environmentFactory = TimerConfiguration.getEnvironmentFactory();
- JobTestHelper jobTestHelper = environmentFactory.get(JobTestHelper.class);
-
- for (int i=0;i<IncrementCounterWaitState.MAX_COUNTER_VALUE;i++) {
- long timerId;
- environmentFactory.openEnvironment();
- try {
- execution =
Environment.getCurrent().get(PvmDbSession.class).get(ExecutionImpl.class, executionId);
- ActivityInstance activityInstance = execution.getActivityInstance();
- Node node = activityInstance.getNode();
- assertEquals("get input", node.getName());
- Set<Timer> timers = activityInstance.getTimers();
- assertNotNull(timers);
- assertEquals(1, timers.size());
- Timer timer = timers.iterator().next();
-
- long difference = timer.getDueDate().getTime() - minimumDueDate;
- assertTrue(difference+" should be positive (iteration
"+i+")", difference >= -200);
- minimumDueDate = Clock.getCurrentTime().getTime() + dayDuration;
- timerId = timer.getDbid();
- } finally {
- Environment.getCurrent().close();
- }
- execution = jobTestHelper.executeTimer(timerId);
+ //TODO: the test fails because the child execution is not deleted and the timer
+ // still exist.
+ //Still, main execution is in the the good state
+ public void testReschedulingTimer() {
+ Date now = Clock.getCurrentTime();
+ long twoDaysFromNow = now.getTime() + twoDaysDuration;
+
+ ProcessDefinition processDefinition =
ProcessFactory.build("reschedulingTimer")
+ .node("decide").initial().behaviour(IncrementCounterWaitState.class)
+ .variable(IncrementCounterWaitState.COUNTER, "0")
+ .timer("2 days", "increment", "2 days")
+ .transition("decision made").to("response") // first defined
transition is the default one
+ .transition("timeout").to("reassign")
+ .node("reassign").behaviour(WaitState.class)
+ .node("response").behaviour(WaitState.class)
+ .done();
+
+ ExecutionImpl processInstance = deployAndInstanciateProcess(processDefinition);
+
+ Execution execution = processInstance;
+ OpenExecution child = ((OpenExecution) execution).getExecutions().iterator().next();
+
+ for (int i=0; i<IncrementCounterWaitState.MAX_COUNTER_VALUE; i++) {
+ // check that the execution is in the right node
+ assertNotNull(child);
+ assertEquals("decide", child.getNodeName());
+ assertEquals(Execution.STATE_ACTIVE, child.getState());
+
+ // check there is one timer
+ assertTrue(child.hasTimers());
+ assertEquals(1, child.getTimers().size());
+
+ // check that timer's dueDate is good
+ Timer timer = child.getTimers().iterator().next();
+ assertTrue("error is
"+(timer.getDueDate().getTime()-twoDaysFromNow)+" millis",
+ twoDaysFromNow <= timer.getDueDate().getTime());
+
+ // execute timer
+ twoDaysFromNow = Clock.getCurrentTime().getTime() + twoDaysDuration - 100;
+ JobTestHelper jobTestHelper = getEnvironmentFactory().get(JobTestHelper.class);
+ jobTestHelper.executeTimer(timer.getDbid());
+ child = loadExecutionFromDb(child.getDbid());
}
-
- environmentFactory.openEnvironment();
- try {
- execution =
Environment.getCurrent().get(PvmDbSession.class).get(ExecutionImpl.class, executionId);
- Node node = execution.getNode();
- assertEquals("process input", node.getName());
-
- assertTrue(execution.getTimers().isEmpty());
- } finally {
- Environment.getCurrent().close();
+
+ // check that the subExecution was deleted
+ if (child!=null) {
+ System.out.println(child.getNodeName());
+ System.out.println(child.getVariable("counter"));
+ execution = loadExecutionFromDb(processInstance.getDbid());
+ System.out.println(execution.getNodeName());
}
-
+ assertNull(child);
+
+ // check that timers have been deleted
+ List<Job> jobs =
Environment.getCurrent().get(PvmDbSession.class).findAllJobs();
+ assertNotNull(jobs);
+ assertTrue(jobs.isEmpty());
+
+ // check that process is in the right state
+ execution = loadExecutionFromDb(processInstance.getDbid());
+ assertEquals("reassign", execution.getNodeName());
}
+ /*
+ TODO finish after refactoring
+
public void testTimerEndingProcess() {
ProcessDefinition processDefinition = ProcessFactory.build("timed2")
.node("get input").initial().behaviour(WaitState.class)