[jbpm-commits] JBoss JBPM SVN: r2555 - in jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm: enterprise/test and 3 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Thu Oct 16 18:56:54 EDT 2008


Author: alex.guizar at jboss.com
Date: 2008-10-16 18:56:53 -0400 (Thu, 16 Oct 2008)
New Revision: 2555

Added:
   jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/EventCallback.java
   jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/msg/jms/JmsMessageTest.java
Removed:
   jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/ActionRecorder.java
   jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/GetCurrentTime.java
   jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/Recorder.java
   jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/msg/jms/AsyncProcessingTest.java
Modified:
   jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/AppServerConfigurationsTest.java
   jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/persistence/jta/JtaDbPersistenceTest.java
   jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/scheduler/ejbtimer/EjbSchedulerTest.java
Log:
merged revisions 2058, 2062, 2072, 2080, 2114, 2134, 2155, 2185, 2218 and 2257 from https://svn.jboss.org/repos/jbpm/jbpm3/trunk/modules/enterprise/jar/src/test/java

Modified: jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/AppServerConfigurationsTest.java
===================================================================
--- jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/AppServerConfigurationsTest.java	2008-10-16 13:32:12 UTC (rev 2554)
+++ jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/AppServerConfigurationsTest.java	2008-10-16 22:56:53 UTC (rev 2555)
@@ -37,17 +37,20 @@
   }
 
   public void testJtaDbPersistenceFactoryConfiguration() {
-    assertSame(JtaDbPersistenceServiceFactory.class, jbpmConfiguration.getServiceFactory(Services.SERVICENAME_PERSISTENCE).getClass());
+    assertSame(JtaDbPersistenceServiceFactory.class, jbpmConfiguration.getServiceFactory(
+        Services.SERVICENAME_PERSISTENCE).getClass());
     JtaDbPersistenceServiceFactory persistenceServiceFactory = (JtaDbPersistenceServiceFactory) jbpmConfiguration.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
     assertFalse(persistenceServiceFactory.isTransactionEnabled());
     assertTrue(persistenceServiceFactory.isCurrentSessionEnabled());
   }
 
   public void testJmsMessageServiceFactoryConfiguration() {
-    assertSame(JmsMessageServiceFactoryImpl.class, jbpmConfiguration.getServiceFactory(Services.SERVICENAME_MESSAGE).getClass());
+    assertSame(JmsMessageServiceFactoryImpl.class, jbpmConfiguration.getServiceFactory(
+        Services.SERVICENAME_MESSAGE).getClass());
   }
 
   public void testEjbSchedulerServiceFactoryConfiguration() {
-    assertSame(EntitySchedulerServiceFactory.class, jbpmConfiguration.getServiceFactory(Services.SERVICENAME_SCHEDULER).getClass());
+    assertSame(EntitySchedulerServiceFactory.class, jbpmConfiguration.getServiceFactory(
+        Services.SERVICENAME_SCHEDULER).getClass());
   }
 }

Deleted: jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/ActionRecorder.java
===================================================================
--- jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/ActionRecorder.java	2008-10-16 13:32:12 UTC (rev 2554)
+++ jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/ActionRecorder.java	2008-10-16 22:56:53 UTC (rev 2555)
@@ -1,37 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jbpm.enterprise.test;
-
-import org.jbpm.graph.def.Action;
-import org.jbpm.graph.exe.ExecutionContext;
-
-public class ActionRecorder extends Recorder {
-
-  private static final long serialVersionUID = 1L;
-
-  public void record(String processInstanceId, ExecutionContext executionContext) {
-    Action action = executionContext.getAction();
-    String actionName = action.getName();
-    collectedResults.add(processInstanceId+actionName);
-  }
-
-}

Added: jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/EventCallback.java
===================================================================
--- jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/EventCallback.java	                        (rev 0)
+++ jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/EventCallback.java	2008-10-16 22:56:53 UTC (rev 2555)
@@ -0,0 +1,146 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.enterprise.test;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.jbpm.JbpmContext;
+import org.jbpm.graph.def.Event;
+
+public class EventCallback implements Serializable {
+
+  private static final long serialVersionUID = 1L;
+  private static final Log log = LogFactory.getLog(EventCallback.class);
+
+  private static Map eventSemaphores = new HashMap();
+
+  public void processStart() {
+    registerNotification(Event.EVENTTYPE_PROCESS_START);
+  }
+
+  public void processEnd() {
+    registerNotification(Event.EVENTTYPE_PROCESS_END);
+  }
+
+  public void nodeEnter() {
+    registerNotification(Event.EVENTTYPE_NODE_ENTER);
+  }
+
+  public void nodeLeave() {
+    registerNotification(Event.EVENTTYPE_NODE_LEAVE);
+  }
+
+  public void taskCreate() {
+    registerNotification(Event.EVENTTYPE_TASK_CREATE);
+  }
+
+  public void taskEnd() {
+    registerNotification(Event.EVENTTYPE_TASK_END);
+  }
+
+  public void timerCreate() {
+    registerNotification(Event.EVENTTYPE_TIMER_CREATE);
+  }
+
+  public void timer() {
+    registerNotification(Event.EVENTTYPE_TIMER);
+  }
+
+  public void transition() {
+    registerNotification(Event.EVENTTYPE_TRANSITION);
+  }
+
+  private static void registerNotification(final String event) {
+    Synchronization notification = new Synchronization() {
+
+      public void beforeCompletion() {
+      }
+
+      public void afterCompletion(int status) {
+        if (status == Status.STATUS_COMMITTED) {
+          log.debug("sending '" + event + "' notification");
+          Semaphore eventSemaphore = getEventSemaphore(event);
+          eventSemaphore.release();
+        }
+      }
+
+    };
+    JbpmContext.getCurrentJbpmContext()
+        .getSession()
+        .getTransaction()
+        .registerSynchronization(notification);
+  }
+
+  public static void waitForEvent(String event) {
+    waitForEvent(event, 10000);
+  }
+
+  public static void waitForEvent(String event, long timeout) {
+    log.debug("waiting for " + event);
+    Semaphore eventSemaphore = getEventSemaphore(event);
+    try {
+      if (eventSemaphore.tryAcquire(timeout, TimeUnit.MILLISECONDS)) {
+        log.debug("received '" + event + "' notification");
+      }
+      else {
+        log.warn("event '" + event + "' did not occur within " + timeout + " ms");
+      }
+    }
+    catch (InterruptedException e) {
+      // reassert interruption
+      Thread.currentThread().interrupt();
+    }
+  }
+
+  private static Semaphore getEventSemaphore(String event) {
+    synchronized (eventSemaphores) {
+      Semaphore semaphore = (Semaphore) eventSemaphores.get(event);
+      if (semaphore == null) {
+        semaphore = new Semaphore(0);
+        eventSemaphores.put(event, semaphore);
+      }
+      return semaphore;
+    }
+  }
+
+  public static void clear() {
+    for (Iterator i = eventSemaphores.entrySet().iterator(); i.hasNext();) {
+      Map.Entry entry = (Map.Entry) i.next();      
+      Semaphore semaphore = (Semaphore) entry.getValue();
+      int permits = semaphore.drainPermits();
+      if (permits != 0) {
+        log.warn("event '" + entry.getKey() + "' has " + permits + " outstanding notifications");
+      }
+    }
+  }
+}
\ No newline at end of file

Deleted: jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/GetCurrentTime.java
===================================================================
--- jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/GetCurrentTime.java	2008-10-16 13:32:12 UTC (rev 2554)
+++ jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/GetCurrentTime.java	2008-10-16 22:56:53 UTC (rev 2555)
@@ -1,34 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jbpm.enterprise.test;
-
-import org.jbpm.graph.def.ActionHandler;
-import org.jbpm.graph.exe.ExecutionContext;
-import org.jbpm.util.Clock;
-
-public class GetCurrentTime implements ActionHandler {
-  String variable;
-  private static final long serialVersionUID = 1L;
-  public void execute(ExecutionContext executionContext) throws Exception {
-    executionContext.setVariable(variable, Clock.getCurrentTime());
-  }
-}
\ No newline at end of file

Deleted: jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/Recorder.java
===================================================================
--- jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/Recorder.java	2008-10-16 13:32:12 UTC (rev 2554)
+++ jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/enterprise/test/Recorder.java	2008-10-16 22:56:53 UTC (rev 2555)
@@ -1,60 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jbpm.enterprise.test;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.TreeSet;
-
-import org.jbpm.graph.def.ActionHandler;
-import org.jbpm.graph.exe.ExecutionContext;
-
-public class Recorder implements ActionHandler {
-
-  private static final long serialVersionUID = 1L;
-  
-  public static Set collectedProcessInstanceIds = null;
-  public static Set collectedResults = null;
-  public volatile static int executions = 0;
-
-  public static void resetCollections() {
-    collectedProcessInstanceIds = Collections.synchronizedSet(new HashSet());
-    collectedResults = Collections.synchronizedSet(new TreeSet());
-    executions = 0;
-  }
-
-  public void execute(ExecutionContext executionContext) throws Exception {
-    synchronized (Recorder.class) {
-      executions++;
-    }
-    String id = (String) Long.toString(executionContext.getProcessInstance().getId());
-    collectedProcessInstanceIds.add(id);
-    record(id, executionContext);
-  }
-
-  public void record(String processInstanceId, ExecutionContext executionContext) {
-    String nodeName = executionContext.getNode().getName();
-    collectedResults.add(processInstanceId+nodeName);
-    executionContext.leaveNode();
-  }
-}

Deleted: jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/msg/jms/AsyncProcessingTest.java
===================================================================
--- jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/msg/jms/AsyncProcessingTest.java	2008-10-16 13:32:12 UTC (rev 2554)
+++ jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/msg/jms/AsyncProcessingTest.java	2008-10-16 22:56:53 UTC (rev 2555)
@@ -1,200 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jbpm.msg.jms;
-
-import java.util.Iterator;
-import java.util.Set;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.TreeSet;
-
-import javax.naming.InitialContext;
-
-import org.apache.cactus.ServletTestCase;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hibernate.Session;
-import org.jbpm.JbpmContext;
-import org.jbpm.command.Command;
-import org.jbpm.command.DeployProcessCommand;
-import org.jbpm.command.StartProcessInstanceCommand;
-import org.jbpm.ejb.LocalCommandService;
-import org.jbpm.ejb.LocalCommandServiceHome;
-import org.jbpm.enterprise.test.ActionRecorder;
-import org.jbpm.enterprise.test.Recorder;
-
-public class AsyncProcessingTest extends ServletTestCase {
-
-  private LocalCommandService commandService;
-
-  static int nbrOfConcurrentProcessExecutions = 20;
-  static int maxWaitTime = 30000;
-
-  protected void setUp() throws Exception {
-    InitialContext initialContext = new InitialContext();
-    LocalCommandServiceHome localCommandServiceHome = (LocalCommandServiceHome) initialContext.lookup("java:comp/env/ejb/LocalCommandServiceBean");
-    commandService = localCommandServiceHome.create();
-  }
-
-  public void testBulkJobs() {
-    Recorder.resetCollections();
-    deleteAllJobs();
-    deployProcess();
-    launchProcesses();
-    processAllJobs(maxWaitTime);
-    Set expectedResults = createExpectedResults();
-    assertEquals(Recorder.collectedProcessInstanceIds.toString()+" wasn't the expected size: "+nbrOfConcurrentProcessExecutions, nbrOfConcurrentProcessExecutions, Recorder.collectedProcessInstanceIds.size());
-    assertEquals(expectedResults, Recorder.collectedResults);
-  }
-
-  protected void deleteAllJobs() {
-    execute( new Command() {
-      private static final long serialVersionUID = 1L;
-      public Object execute(JbpmContext jbpmContext) throws Exception {
-        Session session = jbpmContext.getSession();
-        session.createQuery("delete from org.jbpm.job.Job").executeUpdate();
-        return null;
-      }
-    });
-  }
-
-  protected Object execute(Command command) {
-    return commandService.execute(command);
-  }
-  
-
-  protected void deployProcess() {
-    log.debug("start deploy process");
-    execute(new DeployProcessCommand(
-        "<process-definition name='bulk messages'>" +
-        "  <start-state>" +
-        "    <transition to='a' />" +
-        "  </start-state>" +
-        "  <node name='a' async='true'>" +
-        "    <action class='"+Recorder.class.getName()+"' />" +
-        "    <transition to='b' />" +
-        "  </node>" +
-        "  <node name='b' async='true'>" +
-        "    <event type='node-enter'>" +
-        "      <action name='X' async='true' class='"+ActionRecorder.class.getName()+"' />" +
-        "    </event>" +
-        "    <action class='"+Recorder.class.getName()+"' />" +
-        "    <transition to='c' />" +
-        "  </node>" +
-        "  <node name='c' async='true'>" +
-        "    <action class='"+Recorder.class.getName()+"' />" +
-        "    <transition to='d'>" +
-        "      <action name='Y' async='true' class='"+ActionRecorder.class.getName()+"' />" +
-        "    </transition>" +
-        "  </node>" +
-        "  <node name='d' async='true'>" +
-        "    <action class='"+Recorder.class.getName()+"' />" +
-        "    <transition to='e' />" +
-        "    <event type='node-leave'>" +
-        "      <action name='Z' async='true' class='"+ActionRecorder.class.getName()+"' />" +
-        "    </event>" +
-        "  </node>" +
-        "  <node name='e' async='true'>" +
-        "    <action class='"+Recorder.class.getName()+"' />" +
-        "    <transition to='end' />" +
-        "  </node>" +
-        "  <end-state name='end'/>" +
-        "</process-definition>"));
-  }
-  
-  protected void launchProcesses() {
-    for (int i=0; i<nbrOfConcurrentProcessExecutions; i++) {
-      StartProcessInstanceCommand command = new StartProcessInstanceCommand();
-      command.setProcessName("bulk messages");
-      execute(command);
-    }
-  }
-
-  protected Set createExpectedResults() {
-    Set expectedResults = new TreeSet();
-    Iterator iter = Recorder.collectedProcessInstanceIds.iterator();
-    while (iter.hasNext()) {
-      String id = (String) iter.next();
-      expectedResults.add(id+"a");
-      expectedResults.add(id+"b");
-      expectedResults.add(id+"c");
-      expectedResults.add(id+"d");
-      expectedResults.add(id+"e");
-      expectedResults.add(id+"X");
-      expectedResults.add(id+"Y");
-      expectedResults.add(id+"Z");
-    }
-    return expectedResults;
-  }
-
-  private void processAllJobs(final long maxWait) {
-    boolean jobsAvailable = true;
-
-    // install a timer that will interrupt if it takes too long
-    // if that happens, it will lead to an interrupted exception and the test will fail
-    TimerTask interruptTask = new TimerTask() {
-      Thread testThread = Thread.currentThread();
-      public void run() {
-        log.debug("test "+getName()+" took too long. going to interrupt...");
-        testThread.interrupt();
-      }
-    };
-    Timer timer = new Timer();
-    timer.schedule(interruptTask, maxWait);
-    
-    try {
-      while (jobsAvailable) {
-        log.debug("going to sleep for 200 millis, waiting for the job executor to process more jobs");
-        Thread.sleep(200);
-        jobsAvailable = areJobsAvailable();
-      }
-      
-    } catch (InterruptedException e) {
-      fail("test execution exceeded treshold of "+maxWait+" milliseconds");
-    } finally {
-      timer.cancel();
-    }
-  }
-
-  protected int getNbrOfJobsAvailable() {
-    Integer nbrOfJobsAvailable = (Integer) execute( new Command() {
-      private static final long serialVersionUID = 1L;
-      public Object execute(JbpmContext jbpmContext) throws Exception {
-        Integer nbrOfJobsAvailable = null;
-        Session session = jbpmContext.getSession();
-        Number jobs = (Number) session.createQuery("select count(*) from org.jbpm.job.Job").uniqueResult();
-        log.debug("there are '"+jobs+"' jobs currently in the job table");
-        if (jobs!=null) {
-          nbrOfJobsAvailable = new Integer(jobs.intValue());
-        }
-        return nbrOfJobsAvailable;
-      }
-    });
-    return nbrOfJobsAvailable.intValue();
-  }
-
-  protected boolean areJobsAvailable() {
-    return (getNbrOfJobsAvailable()>0);
-  }
-  
-  private static Log log = LogFactory.getLog(AsyncProcessingTest.class);
-}

Added: jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/msg/jms/JmsMessageTest.java
===================================================================
--- jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/msg/jms/JmsMessageTest.java	                        (rev 0)
+++ jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/msg/jms/JmsMessageTest.java	2008-10-16 22:56:53 UTC (rev 2555)
@@ -0,0 +1,268 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.msg.jms;
+
+import java.util.Collections;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+import org.apache.cactus.ServletTestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.jbpm.enterprise.test.EventCallback;
+import org.jbpm.JbpmContext;
+import org.jbpm.command.Command;
+import org.jbpm.command.DeployProcessCommand;
+import org.jbpm.command.StartProcessInstanceCommand;
+import org.jbpm.ejb.LocalCommandService;
+import org.jbpm.ejb.LocalCommandServiceHome;
+import org.jbpm.graph.def.Event;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.graph.exe.ProcessInstance;
+
+/**
+ * Exercises for the {@linkplain JmsMessageServiceImpl JMS message service}.
+ * @author Alejandro Guizar
+ */
+public class JmsMessageTest extends ServletTestCase {
+
+  private LocalCommandService commandService;
+
+  private static LocalCommandServiceHome commandServiceHome;
+
+  static final int processExecutionCount = 20;
+  static final int maxWaitTime = 10000;
+
+  protected void setUp() throws Exception {
+    if (commandServiceHome == null) {
+      Context initialContext = new InitialContext();
+      try {
+        commandServiceHome = (LocalCommandServiceHome) initialContext.lookup("java:comp/env/ejb/LocalCommandServiceBean");
+      }
+      finally {
+        initialContext.close();
+      }
+    }
+    commandService = commandServiceHome.create();
+    log.info("### " + getName() + " started ###");
+  }
+
+  protected void tearDown() throws Exception {
+    log.info("### " + getName() + " done ###");
+    EventCallback.clear();
+    commandService = null;
+  }
+
+  public void testAsyncNode() {
+    deployProcess("<process-definition name='node'>"
+        + "  <event type='process-end'>"
+        + "    <action expression='#{eventCallback.processEnd}'/>"
+        + "  </event>"
+        + "  <start-state name='start'>"
+        + "    <transition to='a' />"
+        + "  </start-state>"
+        + "  <node name='a' async='true'>"
+        + "    <transition to='end' />"
+        + "  </node>"
+        + "  <end-state name='end' />"
+        + "</process-definition>");
+    long processId = launchProcess("node").getId();
+    EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
+    assertTrue(hasProcessEnded(processId));
+  }
+
+  public void testAsyncAction() {
+    deployProcess("<process-definition name='action'>"
+        + "  <start-state name='start'>"
+        + "    <transition to='a' />"
+        + "  </start-state>"
+        + "  <node name='a'>"
+        + "    <event type='node-enter'>"
+        + "      <action async='true' expression='#{eventCallback.nodeEnter}' />"
+        + "    </event>"
+        + "    <event type='node-leave'>"
+        + "      <action async='true' expression='#{eventCallback.nodeLeave}' />"
+        + "    </event>"
+        + "    <transition to='end'>"
+        + "      <action async='true' expression='#{eventCallback.transition}' />"
+        + "    </transition>"
+        + "  </node>"
+        + "  <end-state name='end' />"
+        + "</process-definition>");
+    long processId = launchProcess("action").getId();
+    EventCallback.waitForEvent(Event.EVENTTYPE_NODE_ENTER);
+    EventCallback.waitForEvent(Event.EVENTTYPE_NODE_LEAVE);
+    EventCallback.waitForEvent(Event.EVENTTYPE_TRANSITION);
+    assertTrue(hasProcessEnded(processId));
+  }
+
+  public void testAsyncSequence() {
+    deployProcess("<process-definition name='sequence'>"
+        + "  <event type='process-end'>"
+        + "    <action expression='#{eventCallback.processEnd}'/>"
+        + "  </event>"
+        + "  <start-state>"
+        + "    <transition to='a' />"
+        + "  </start-state>"
+        + "  <node name='a' async='true'>"
+        + "    <transition to='b' />"
+        + "  </node>"
+        + "  <node name='b' async='true'>"
+        + "    <transition to='c' />"
+        + "  </node>"
+        + "  <node name='c' async='true'>"
+        + "    <transition to='d' />"
+        + "  </node>"
+        + "  <node name='d' async='true'>"
+        + "    <transition to='e' />"
+        + "  </node>"
+        + "  <node name='e' async='true'>"
+        + "    <transition to='end' />"
+        + "  </node>"
+        + "  <end-state name='end' />"
+        + "</process-definition>");
+    long processId = launchProcess("sequence").getId();
+    EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
+    assertTrue(hasProcessEnded(processId));
+  }
+
+  public void testAsyncFork() {
+    deployProcess("<process-definition name='fork'>"
+        + "  <event type='process-end'>"
+        + "    <action expression='#{eventCallback.processEnd}'/>"
+        + "  </event>"
+        + "  <start-state>"
+        + "    <transition to='f' />"
+        + "  </start-state>"
+        + "  <fork name='f'>"
+        + "    <transition name='a' to='a' />"
+        + "    <transition name='b' to='b' />"
+        + "    <transition name='c' to='c' />"
+        + "    <transition name='d' to='d' />"
+        + "    <transition name='e' to='e' />"
+        + "  </fork>"
+        + "  <node name='a'>"
+        + "    <transition to='j' />"
+        + "  </node>"
+        + "  <node name='b' async='true'>"
+        + "    <transition to='j' />"
+        + "  </node>"
+        + "  <node name='c' async='true'>"
+        + "    <transition to='j' />"
+        + "  </node>"
+        + "  <node name='d' async='true'>"
+        + "    <transition to='j' />"
+        + "  </node>"
+        + "  <node name='e' async='true'>"
+        + "    <transition to='j' />"
+        + "  </node>"
+        + "  <join name='j'>"
+        + "    <transition to='end' />"
+        + "  </join>"
+        + "  <end-state name='end' />"
+        + "</process-definition>");
+    long processId = launchProcess("fork").getId();
+    EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
+    assertTrue(hasProcessEnded(processId));
+  }
+
+  public void testAsyncExecutions() {
+    deployProcess("<process-definition name='execution'>"
+        + "  <event type='process-end'>"
+        + "    <action expression='#{eventCallback.processEnd}' />"
+        + "  </event>"
+        + "  <start-state>"
+        + "    <transition to='a' />"
+        + "  </start-state>"
+        + "  <node name='a' async='true'>"
+        + "    <transition to='b' />"
+        + "  </node>"
+        + "  <node name='b'>"
+        + "    <event type='node-enter'>"
+        + "      <action async='true' expression='#{eventCallback.nodeEnter}' />"
+        + "    </event>"
+        + "    <transition to='c' />"
+        + "  </node>"
+        + "  <node name='c' async='true'>"
+        + "    <transition to='d' />"
+        + "  </node>"
+        + "  <node name='d'>"
+        + "    <event type='node-leave'>"
+        + "      <action async='true' expression='#{eventCallback.nodeLeave}' />"
+        + "    </event>"
+        + "    <transition to='e' />"
+        + "  </node>"
+        + "  <node name='e' async='true'>"
+        + "    <transition to='end' />"
+        + "  </node>"
+        + "  <end-state name='end' />"
+        + "</process-definition>");
+    long[] processIds = new long[processExecutionCount];
+    for (int i = 0; i < processExecutionCount; i++) {
+      processIds[i] = launchProcess("execution").getId();
+      EventCallback.waitForEvent(Event.EVENTTYPE_NODE_ENTER);
+      EventCallback.waitForEvent(Event.EVENTTYPE_NODE_LEAVE);
+    }
+    for (int i = 0; i < processExecutionCount; i++) {
+      waitForProcessEnd(processIds[i]);
+      assertTrue(hasProcessEnded(processIds[i]));
+    }
+  }
+
+  private ProcessDefinition deployProcess(String xml) {
+    return (ProcessDefinition) commandService.execute(new DeployProcessCommand(xml));
+  }
+
+  private ProcessInstance launchProcess(String processName) {
+    StartProcessInstanceCommand command = new StartProcessInstanceCommand();
+    command.setProcessName(processName);
+    command.setVariables(Collections.singletonMap("eventCallback", new EventCallback()));
+    return (ProcessInstance) commandService.execute(command);
+  }
+
+  private boolean hasProcessEnded(final long processId) {
+    Boolean isFinished = (Boolean) commandService.execute(new Command() {
+
+      private static final long serialVersionUID = 1L;
+
+      public Object execute(JbpmContext jbpmContext) throws Exception {
+        return jbpmContext.loadProcessInstance(processId).hasEnded();
+      }
+    });
+    return isFinished.booleanValue();
+  }
+
+  private void waitForProcessEnd(long processId) {
+    long startTime = System.currentTimeMillis();
+    do {
+      EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END, 1000);
+      if (System.currentTimeMillis() - startTime > maxWaitTime) {
+        log.warn("process " + processId + " took too long");
+        break;
+      }
+    } while (!hasProcessEnded(processId));
+  }
+
+  private static Log log = LogFactory.getLog(JmsMessageTest.class);
+}

Modified: jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/persistence/jta/JtaDbPersistenceTest.java
===================================================================
--- jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/persistence/jta/JtaDbPersistenceTest.java	2008-10-16 13:32:12 UTC (rev 2554)
+++ jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/persistence/jta/JtaDbPersistenceTest.java	2008-10-16 22:56:53 UTC (rev 2555)
@@ -42,7 +42,6 @@
 
   protected void setUp() throws Exception {
     jbpmConfiguration = JbpmConfiguration.getInstance();
-    getUserTransaction();
   }
 
   public void testUserTx() throws Exception {
@@ -73,7 +72,8 @@
   private long deployProcess() throws Exception {
     if (definitionId == 0) {
       try {
-        if (tx != null) tx.begin();
+        if (tx != null)
+          tx.begin();
         JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
         try {
           assertEquals(tx == null, isTxCreatedByService(jbpmContext));
@@ -90,16 +90,19 @@
           definitionId = definition.getId();
         }
         catch (RuntimeException e) {
-          if (tx == null) jbpmContext.setRollbackOnly();
+          if (tx == null)
+            jbpmContext.setRollbackOnly();
           throw e;
         }
         finally {
           jbpmContext.close();
         }
-        if (tx != null) tx.commit();
+        if (tx != null)
+          tx.commit();
       }
       catch (Exception e) {
-        if (tx != null) tx.rollback();
+        if (tx != null)
+          tx.rollback();
         throw e;
       }
     }
@@ -108,7 +111,8 @@
 
   private long launchProcess(long definitionId) throws Exception {
     try {
-      if (tx != null) tx.begin();
+      if (tx != null)
+        tx.begin();
       JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
       ProcessInstance instance;
       try {
@@ -120,54 +124,62 @@
         jbpmContext.save(instance);
       }
       catch (RuntimeException e) {
-        if (tx == null) jbpmContext.setRollbackOnly();
+        if (tx == null)
+          jbpmContext.setRollbackOnly();
         throw e;
       }
       finally {
         jbpmContext.close();
       }
-      if (tx != null) tx.commit();
+      if (tx != null)
+        tx.commit();
       return instance.getId();
     }
     catch (Exception e) {
-      if (tx != null) tx.rollback();
+      if (tx != null)
+        tx.rollback();
       throw e;
     }
   }
 
   private void signal(long instanceId) throws Exception {
     try {
-      if (tx != null) tx.begin();
+      if (tx != null)
+        tx.begin();
       JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
       try {
         assertEquals(tx == null, isTxCreatedByService(jbpmContext));
         ProcessInstance instance = jbpmContext.loadProcessInstanceForUpdate(instanceId);
         instance.signal();
-        if (rollback && tx == null) jbpmContext.setRollbackOnly();
+        if (rollback && tx == null)
+          jbpmContext.setRollbackOnly();
       }
       catch (RuntimeException e) {
-        if (tx == null) jbpmContext.setRollbackOnly();
+        if (tx == null)
+          jbpmContext.setRollbackOnly();
         throw e;
       }
       finally {
         jbpmContext.close();
       }
       if (tx != null) {
-        if (rollback) 
+        if (rollback)
           tx.rollback();
         else
           tx.commit();
       }
     }
     catch (Exception e) {
-      if (tx != null) tx.rollback();
+      if (tx != null)
+        tx.rollback();
       throw e;
     }
   }
 
   private boolean hasEnded(long instanceId) throws Exception {
     try {
-      if (tx != null) tx.begin();
+      if (tx != null)
+        tx.begin();
       JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
       ProcessInstance instance;
       try {
@@ -175,17 +187,20 @@
         instance = jbpmContext.loadProcessInstanceForUpdate(instanceId);
       }
       catch (RuntimeException e) {
-        if (tx == null) jbpmContext.setRollbackOnly();
+        if (tx == null)
+          jbpmContext.setRollbackOnly();
         throw e;
       }
       finally {
         jbpmContext.close();
       }
-      if (tx != null) tx.commit();
+      if (tx != null)
+        tx.commit();
       return instance.hasEnded();
     }
     catch (Exception e) {
-      if (tx != null) tx.rollback();
+      if (tx != null)
+        tx.rollback();
       throw e;
     }
   }

Modified: jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/scheduler/ejbtimer/EjbSchedulerTest.java
===================================================================
--- jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/scheduler/ejbtimer/EjbSchedulerTest.java	2008-10-16 13:32:12 UTC (rev 2554)
+++ jbpm3/branches/jpdl-3.2.3.GA_JBPM-1704/enterprise/src/test/java/org/jbpm/scheduler/ejbtimer/EjbSchedulerTest.java	2008-10-16 22:56:53 UTC (rev 2555)
@@ -21,257 +21,292 @@
  */
 package org.jbpm.scheduler.ejbtimer;
 
+import java.util.Collections;
+
+import javax.naming.Context;
 import javax.naming.InitialContext;
 
 import org.apache.cactus.ServletTestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.jbpm.enterprise.test.EventCallback;
 import org.jbpm.JbpmContext;
 import org.jbpm.command.Command;
 import org.jbpm.command.DeployProcessCommand;
 import org.jbpm.command.StartProcessInstanceCommand;
 import org.jbpm.ejb.LocalCommandService;
 import org.jbpm.ejb.LocalCommandServiceHome;
-import org.jbpm.enterprise.test.ActionRecorder;
-import org.jbpm.enterprise.test.GetCurrentTime;
-import org.jbpm.enterprise.test.Recorder;
+import org.jbpm.graph.def.Event;
 import org.jbpm.graph.def.ProcessDefinition;
 import org.jbpm.graph.exe.ProcessInstance;
 import org.jbpm.graph.exe.Token;
 
+/**
+ * Exercises for the {@linkplain EntitySchedulerService EJB scheduler service}.
+ * @author Alejandro Guizar
+ */
 public class EjbSchedulerTest extends ServletTestCase {
-  
+
   private LocalCommandService commandService;
 
   private static LocalCommandServiceHome commandServiceHome;
 
+  private static final Log log = LogFactory.getLog(EjbSchedulerTest.class);
+
   protected void setUp() throws Exception {
     if (commandServiceHome == null) {
-      InitialContext initialContext = new InitialContext();
-      commandServiceHome = (LocalCommandServiceHome) initialContext.lookup("java:comp/env/ejb/LocalCommandServiceBean");
+      Context initialContext = new InitialContext();
+      try {
+        commandServiceHome = (LocalCommandServiceHome) initialContext.lookup("java:comp/env/ejb/LocalCommandServiceBean");
+      }
+      finally {
+        initialContext.close();
+      }
     }
     commandService = commandServiceHome.create();
+    log.info("### " + getName() + " started ###");
   }
 
   protected void tearDown() throws Exception {
+    log.info("### " + getName() + " done ###");
     commandService = null;
   }
 
   public void testScheduleFuture() throws Exception {
-    Recorder.resetCollections();
-    deployProcess(
-        "<process-definition name='timer included'>" +
-        "  <start-state>" +
-        "    <transition to='a' />" +
-        "  </start-state>" +
-        "  <state name='a'>" +
-        "    <timer duedate='1 second'>" +
-        "      <action class='" + ActionRecorder.class.getName() + "' />" +
-        "    </timer>" +
-        "  </state>" +
-        "</process-definition>");
-    launchProcess("timer included");
-    assertEquals(0, Recorder.executions);
-    Thread.sleep(500);
-    assertEquals(0, Recorder.executions);
-    Thread.sleep(1000);
-    assertEquals(1, Recorder.executions);
+    deployProcess("<process-definition name='future'>"
+        + "  <event type='process-end'>"
+        + "    <action expression='#{eventCallback.processEnd}'/>"
+        + "  </event>"
+        + "  <start-state name='start'>"
+        + "    <transition to='a' />"
+        + "  </start-state>"
+        + "  <state name='a'>"
+        + "    <timer duedate='1 second' transition='timeout' />"
+        + "    <transition name='timeout' to='end' />"
+        + "  </state>"
+        + "  <end-state name='end' />"
+        + "</process-definition>");
+    long processId = launchProcess("future").getId();
+    EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
+    assertTrue(isProcessFinished(processId));
   }
 
   public void testSchedulePast() throws Exception {
-    Recorder.resetCollections();
-    deployProcess(
-        "<process-definition name='timer included'>" +
-        "  <start-state>" +
-        "    <transition to='a'>" +
-        "      <action class='" + GetCurrentTime.class.getName() + "'>" +
-        "        <variable>now</variable>" +
-        "      </action>" +
-        "    </transition>" +
-        "  </start-state>" +
-        "  <state name='a'>" +
-        "    <timer duedate='#{now} - 1 second'>" +
-        "      <action class='" + ActionRecorder.class.getName() + "' />" +
-        "    </timer>" +
-        "  </state>" +
-        "</process-definition>");
-    launchProcess("timer included");
-    assertEquals(0, Recorder.executions);
-    Thread.sleep(500);
-    assertEquals(1, Recorder.executions);
+    deployProcess("<process-definition name='past'>"
+        + "  <event type='process-end'>"
+        + "    <action expression='#{eventCallback.processEnd}'/>"
+        + "  </event>"
+        + "  <start-state name='start'>"
+        + "    <transition to='a' />"
+        + "  </start-state>"
+        + "  <state name='a'>"
+        + "    <timer duedate='-1 second' transition='timeout' />"
+        + "    <transition name='timeout' to='end' />"
+        + "  </state>"
+        + "  <end-state name='end' />"
+        + "</process-definition>");
+    long processId = launchProcess("past").getId();
+    EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
+    assertTrue(isProcessFinished(processId));
   }
 
   public void testScheduleRepeat() throws Exception {
-    Recorder.resetCollections();
-    deployProcess(
-        "<process-definition name='repeat included'>" +
-        "  <start-state>" +
-        "    <transition to='a' />" +
-        "  </start-state>" +
-        "  <state name='a'>" +
-        "    <timer duedate='1 second' repeat='2 seconds'>" +
-        "      <action class='" + ActionRecorder.class.getName() + "' />" +
-        "    </timer>" +
-        "  </state>" +
-        "</process-definition>");
-    long tokenId = launchProcess("repeat included").getRootToken().getId();
-    assertEquals(0, Recorder.executions);
-    Thread.sleep(500);
-    assertEquals(0, Recorder.executions);
-    Thread.sleep(1000);
-    assertEquals(1, Recorder.executions);
-    Thread.sleep(1000);
-    assertEquals(1, Recorder.executions);
-    Thread.sleep(1000);
-    assertEquals(2, Recorder.executions);
-    cancelTimer("a", tokenId);
+    deployProcess("<process-definition name='repeat'>"
+        + "  <event type='timer'>"
+        + "    <action expression='#{eventCallback.timer}'/>"
+        + "  </event>"
+        + "  <start-state name='start'>"
+        + "    <transition to='a' />"
+        + "  </start-state>"
+        + "  <state name='a'>"
+        + "    <timer duedate='1 second' repeat='1 second' />"
+        + "    <transition to='end' />"
+        + "  </state>"
+        + "  <end-state name='end' />"
+        + "</process-definition>");
+    long processId = launchProcess("repeat").getId();
+    for (int i = 0; i < 3; i++) {
+      EventCallback.waitForEvent(Event.EVENTTYPE_TIMER);
+      assertEquals("a", getProcessState(processId));
+    }
+    signalProcess(processId);
+    assertTrue(isProcessFinished(processId));
   }
 
   public void testCancel() throws Exception {
-    Recorder.resetCollections();
-    deployProcess(
-        "<process-definition name='repeat included'>" +
-        "  <start-state>" +
-        "    <transition to='a' />" +
-        "  </start-state>" +
-        "  <state name='a'>" +
-        "    <timer duedate='1 second' repeat='1 second'>" +
-        "      <action class='" + ActionRecorder.class.getName() + "' />" +
-        "    </timer>" +
-        "  </state>" +
-        "</process-definition>");
-    long tokenId = launchProcess("repeat included").getRootToken().getId();
-    assertEquals(0, Recorder.executions);
-    Thread.sleep(500);
-    assertEquals(0, Recorder.executions);
-    Thread.sleep(1000);
-    assertEquals(1, Recorder.executions);
-    cancelTimer("a", tokenId);
-    Thread.sleep(1000);
-    assertEquals(1, Recorder.executions);
-    Thread.sleep(1000);
-    assertEquals(1, Recorder.executions);
+    deployProcess("<process-definition name='cancel'>"
+        + "  <event type='timer'>"
+        + "    <action expression='#{eventCallback.timer}'/>"
+        + "  </event>"
+        + "  <start-state name='start'>"
+        + "    <transition to='a' />"
+        + "  </start-state>"
+        + "  <state name='a'>"
+        + "    <timer duedate='1 second' repeat='1 second' />"
+        + "    <transition to='end' />"
+        + "  </state>"
+        + "  <end-state name='end' />"
+        + "</process-definition>");
+    ProcessInstance process = launchProcess("cancel");
+    long processId = process.getId();
+    // first expiration
+    EventCallback.waitForEvent(Event.EVENTTYPE_TIMER);
+    assertEquals("a", getProcessState(processId));
+    // repeated expiration
+    EventCallback.waitForEvent(Event.EVENTTYPE_TIMER);
+    assertEquals("a", getProcessState(processId));
+    // no more expirations
+    cancelTimer("a", process.getRootToken().getId());
+    EventCallback.waitForEvent(Event.EVENTTYPE_TIMER, 2000);
+    signalProcess(processId);
+    assertTrue(isProcessFinished(processId));
   }
 
-  public void testScheduleMultiple() throws Exception {
-    Recorder.resetCollections();
-    deployProcess(
-        "<process-definition name='timers included'>" +
-        "  <start-state>" +
-        "    <transition to='a' />" +
-        "  </start-state>" +
-        "  <state name='a'>" +
-        "    <timer duedate='500 milliseconds' transition='next'>" +
-        "      <action class='" + ActionRecorder.class.getName() + "' />" +
-        "    </timer>" +
-        "    <transition name='next' to='b' />" +
-        "  </state>" +
-        "  <state name='b'>" +
-        "    <timer duedate='500 milliseconds' transition='next'>" +
-        "      <action class='" + ActionRecorder.class.getName() + "' />" +
-        "    </timer>" +
-        "    <transition name='next' to='c' />" +
-        "  </state>" +
-        "  <state name='c'>" +
-        "    <timer duedate='500 milliseconds' transition='next'>" +
-        "      <action class='" + ActionRecorder.class.getName() + "' />" +
-        "    </timer>" +
-        "    <transition name='next' to='d' />" +
-        "  </state>" +
-        "  <state name='d'>" +
-        "    <timer duedate='500 milliseconds' transition='next'>" +
-        "      <action class='" + ActionRecorder.class.getName() + "' />" +
-        "    </timer>" +
-        "    <transition name='next' to='e' />" +
-        "  </state>" +
-        "  <state name='e'>" +
-        "    <timer duedate='500 milliseconds'>" +
-        "      <action class='" + ActionRecorder.class.getName() + "' />" +
-        "    </timer>" +
-        "  </state>" +
-        "</process-definition>");
-    launchProcess("timers included");
-    assertEquals(0, Recorder.executions);
-    Thread.sleep(250);
-    assertEquals(0, Recorder.executions);
-    for (int i = 1; i <= 5; i++) {
-      Thread.sleep(500);
-      assertEquals(i, Recorder.executions);
+  public void testScheduleSequence() throws Exception {
+    deployProcess("<process-definition name='sequence'>"
+        + "  <event type='process-end'>"
+        + "    <action expression='#{eventCallback.processEnd}'/>"
+        + "  </event>"
+        + "  <event type='timer'>"
+        + "    <action expression='#{eventCallback.timer}'/>"
+        + "  </event>"
+        + "  <start-state>"
+        + "    <transition to='a' />"
+        + "  </start-state>"
+        + "  <state name='a'>"
+        + "    <timer duedate='500 milliseconds' transition='timeout' />"
+        + "    <transition name='timeout' to='b' />"
+        + "  </state>"
+        + "  <state name='b'>"
+        + "    <timer duedate='500 milliseconds' transition='timeout' />"
+        + "    <transition name='timeout' to='c' />"
+        + "  </state>"
+        + "  <state name='c'>"
+        + "    <timer duedate='500 milliseconds' transition='timeout' />"
+        + "    <transition name='timeout' to='d' />"
+        + "  </state>"
+        + "  <state name='d'>"
+        + "    <timer duedate='500 milliseconds' transition='timeout' />"
+        + "    <transition name='timeout' to='e' />"
+        + "  </state>"
+        + "  <state name='e'>"
+        + "    <timer duedate='500 milliseconds' transition='timeout' />"
+        + "    <transition name='timeout' to='end' />"
+        + "  </state>"
+        + "  <end-state name='end' />"
+        + "</process-definition>");
+    long processId = launchProcess("sequence").getId();
+    char state = 'b';
+    for (int i = 0; i < 4; i++) {
+      EventCallback.waitForEvent(Event.EVENTTYPE_TIMER);
+      assertEquals(Character.toString(state++), getProcessState(processId));
     }
+    EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
+    assertTrue(isProcessFinished(processId));
   }
 
-  public void testScheduleConcurrent() throws InterruptedException {
-    Recorder.resetCollections();
-    deployProcess(
-        "<process-definition name='timers included'>" +
-        "  <start-state>" +
-        "    <transition to='f' />" +
-        "  </start-state>" +
-        "  <fork name='f'>" +
-        "    <transition name='a' to='a' />" +
-        "    <transition name='b' to='b' />" +
-        "    <transition name='c' to='c' />" +
-        "    <transition name='d' to='d' />" +
-        "    <transition name='e' to='e' />" +
-        "  </fork>" +
-        "  <state name='a'>" +
-        "    <timer duedate='1 second'>" +
-        "      <action class='" + ActionRecorder.class.getName() + "' />" +
-        "    </timer>" +
-        "  </state>" +
-        "  <state name='b'>" +
-        "    <timer duedate='1 second'>" +
-        "      <action class='" + ActionRecorder.class.getName() + "' />" +
-        "    </timer>" +
-        "  </state>" +
-        "  <state name='c'>" +
-        "    <timer duedate='1 second'>" +
-        "      <action class='" + ActionRecorder.class.getName() + "' />" +
-        "    </timer>" +
-        "  </state>" +
-        "  <state name='d'>" +
-        "    <timer duedate='1 second'>" +
-        "      <action class='" + ActionRecorder.class.getName() + "' />" +
-        "    </timer>" +
-        "  </state>" +
-        "  <state name='e'>" +
-        "    <timer duedate='1 second'>" +
-        "      <action class='" + ActionRecorder.class.getName() + "' />" +
-        "    </timer>" +
-        "  </state>" +
-        "</process-definition>");
-    launchProcess("timers included");
-    assertEquals(0, Recorder.executions);
-    Thread.sleep(500);
-    assertEquals(0, Recorder.executions);
-    Thread.sleep(1000);
-    assertEquals(5, Recorder.executions);
+  public void testScheduleFork() throws InterruptedException {
+    deployProcess("<process-definition name='fork'>"
+        + "  <event type='process-end'>"
+        + "    <action expression='#{eventCallback.processEnd}'/>"
+        + "  </event>"
+        + "  <start-state>"
+        + "    <transition to='f' />"
+        + "  </start-state>"
+        + "  <fork name='f'>"
+        + "    <transition name='a' to='a' />"
+        + "    <transition name='b' to='b' />"
+        + "    <transition name='c' to='c' />"
+        + "    <transition name='d' to='d' />"
+        + "    <transition name='e' to='e' />"
+        + "  </fork>"
+        + "  <state name='a'>"
+        + "    <timer duedate='0.25 seconds' transition='timeout' />"
+        + "    <transition name='timeout' to='j' />"
+        + "  </state>"
+        + "  <state name='b'>"
+        + "    <timer duedate='0.5 seconds' transition='timeout' />"
+        + "    <transition name='timeout' to='j' />"
+        + "  </state>"
+        + "  <state name='c'>"
+        + "    <timer duedate='0.75 seconds' transition='timeout' />"
+        + "    <transition name='timeout' to='j' />"
+        + "  </state>"
+        + "  <state name='d'>"
+        + "    <timer duedate='1 second' transition='timeout' />"
+        + "    <transition name='timeout' to='j' />"
+        + "  </state>"
+        + "  <state name='e'>"
+        + "    <timer duedate='1.25 second' transition='timeout' />"
+        + "    <transition name='timeout' to='j' />"
+        + "  </state>"
+        + "  <join name='j'>"
+        + "    <transition to='end' />"
+        + "  </join>"
+        + "  <end-state name='end' />"
+        + "</process-definition>");
+    long processId = launchProcess("fork").getId();
+    EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
+    assertTrue(isProcessFinished(processId));
   }
 
-  protected ProcessDefinition deployProcess(String xml) {
+  private ProcessDefinition deployProcess(String xml) {
     return (ProcessDefinition) commandService.execute(new DeployProcessCommand(xml));
   }
-  
-  protected ProcessInstance launchProcess(final String processName) {
+
+  private ProcessInstance launchProcess(String processName) {
     StartProcessInstanceCommand command = new StartProcessInstanceCommand();
     command.setProcessName(processName);
+    command.setVariables(Collections.singletonMap("eventCallback", new EventCallback()));
     return (ProcessInstance) commandService.execute(command);
   }
 
-  protected void cancelTimer(String timerName, long tokenId) {
-    commandService.execute(new CancelTimerCommand(timerName, tokenId));
+  private void signalProcess(final long processId) {
+    commandService.execute(new Command() {
+
+      private static final long serialVersionUID = 1L;
+
+      public Object execute(JbpmContext jbpmContext) throws Exception {
+        jbpmContext.loadProcessInstanceForUpdate(processId).signal();
+        return null;
+      }
+    });
   }
 
-  protected static class CancelTimerCommand implements Command {
-    final String timerName;
-    final long tokenId;
-    private static final long serialVersionUID = 1L;
-    public CancelTimerCommand(String timerName, long tokenId) {
-      this.timerName = timerName;
-      this.tokenId = tokenId;
-    }
-    public Object execute(JbpmContext jbpmContext) throws Exception {
-      Token token = jbpmContext.loadToken(tokenId);
-      jbpmContext.getJobSession().cancelTimersByName(timerName, token);
-      return null;
-    }
+  private String getProcessState(final long processId) {
+    return (String) commandService.execute(new Command() {
+
+      private static final long serialVersionUID = 1L;
+
+      public Object execute(JbpmContext jbpmContext) throws Exception {
+        return jbpmContext.loadProcessInstance(processId).getRootToken().getNode().getName();
+      }
+    });
   }
+
+  private boolean isProcessFinished(final long processId) {
+    Boolean isFinished = (Boolean) commandService.execute(new Command() {
+
+      private static final long serialVersionUID = 1L;
+
+      public Object execute(JbpmContext jbpmContext) throws Exception {
+        return jbpmContext.loadProcessInstance(processId).hasEnded();
+      }
+    });
+    return isFinished.booleanValue();
+  }
+
+  private void cancelTimer(final String timerName, final long tokenId) {
+    commandService.execute(new Command() {
+
+      private static final long serialVersionUID = 1L;
+
+      public Object execute(JbpmContext jbpmContext) throws Exception {
+        Token token = jbpmContext.loadToken(tokenId);
+        jbpmContext.getServices().getSchedulerService().deleteTimersByName(timerName, token);
+        return null;
+      }
+    });
+  }
 }




More information about the jbpm-commits mailing list