package org.jbpm.jbpm2036; import org.jbpm.context.exe.ContextInstance; import org.jbpm.db.AbstractDbTestCase; import org.jbpm.graph.def.ActionHandler; import org.jbpm.graph.def.ProcessDefinition; import org.jbpm.graph.exe.ExecutionContext; import org.jbpm.graph.exe.ProcessInstance; /** * StaleObjectStateException when repeating timer signals the token. * * @see <a href="https://jira.jboss.org/jira/browse/JBPM-2036">JBPM-2036</a> * @author Thomas.Diesler@jboss.com * @since 11-Feb-2009 */ public class JBPM2036Test extends AbstractDbTestCase { public void testTimerAction() { ProcessDefinition processDefinition = getProcessDefinition(); deployProcessDefinition(processDefinition); ProcessInstance processInstance = new ProcessInstance(processDefinition); processInstance.signal(); jbpmContext.save(processInstance); processJobs(); processInstance = jbpmContext.loadProcessInstance(processInstance.getId()); assertTrue("expected " + processInstance + " to have ended", processInstance.hasEnded()); ContextInstance contextInstance = processInstance.getContextInstance(); Integer count = (Integer) contextInstance.getVariable("chaos"); assertEquals(1, count.intValue()); count = (Integer) contextInstance.getVariable("undead"); assertEquals(1, count.intValue()); } private static ProcessDefinition getProcessDefinition() { return ProcessDefinition.parseXmlString("<process-definition name='jbpm2036'>" + " <start-state name='start'>" + " <transition to='midway'/>" + " </start-state>" + " <task-node name='midway' end-tasks='yes'>" + " <timer name='chaos' duedate='2 seconds' repeat='5 seconds'>" + " <action class='" + TimerAction.class.getName() + "'>" + " <leave>true</leave>" + " </action>" + " </timer>" + " <task name='doit'>" + " <timer name='undead' duedate='1 second' repeat='5 seconds'>" + " <action class='" + TimerAction.class.getName() + "'/>" + " </timer>" + " </task>" + " <transition to='end'/>" + " </task-node>" + " <end-state name='end' />" + "</process-definition>"); } public static class TimerAction implements ActionHandler { private boolean leave; private static final long serialVersionUID = 1L; public void execute(ExecutionContext executionContext) throws Exception { String timerName = executionContext.getTimer().getName(); Integer count = (Integer) executionContext.getVariable(timerName); executionContext.setVariable(timerName, new Integer(count != null ? count.intValue() + 1 : 1)); if (leave) executionContext.leaveNode(); } } }