[jbpm-commits] JBoss JBPM SVN: r5924 - in jbpm4/trunk/modules: jpdl/src/main/java/org/jbpm/jpdl/internal/activity and 6 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Tue Dec 8 08:28:57 EST 2009


Author: jbarrez
Date: 2009-12-08 08:28:56 -0500 (Tue, 08 Dec 2009)
New Revision: 5924

Modified:
   jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch02-Incubation.xml
   jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/TaskActivity.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/cmd/CompleteTaskCmd.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/cmd/GetOutcomes.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/svc/TaskServiceImpl.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/task/TaskImpl.java
   jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/task/TaskCompletionTest.java
   jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/task/TaskOutcomesTest.java
   jbpm4/trunk/modules/test-db/src/test/resources/logging.properties
   jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Services.xml
Log:
Fix for JBPM-2492 : improve task outcomes

Modified: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch02-Incubation.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch02-Incubation.xml	2009-12-08 03:33:29 UTC (rev 5923)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch02-Incubation.xml	2009-12-08 13:28:56 UTC (rev 5924)
@@ -745,13 +745,6 @@
     </para>
 
   </section>
-
-  <section>
-    <title>Task outcomes</title>
-    <para>Task outcomes might be changed as it is still being discussed
-    <ulink url="http://www.jboss.org/index.html?module=bb&amp;op=viewtopic&amp;p=4241828">here</ulink> 
-    </para>
-  </section>
   
   <section id="taskforms">
     <title>Task forms</title>

Modified: jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/TaskActivity.java
===================================================================
--- jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/TaskActivity.java	2009-12-08 03:33:29 UTC (rev 5923)
+++ jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/TaskActivity.java	2009-12-08 13:28:56 UTC (rev 5924)
@@ -21,12 +21,12 @@
  */
 package org.jbpm.jpdl.internal.activity;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
 import org.jbpm.api.JbpmException;
 import org.jbpm.api.activity.ActivityExecution;
-import org.jbpm.api.task.Task;
 import org.jbpm.internal.log.Log;
 import org.jbpm.pvm.internal.env.EnvironmentImpl;
 import org.jbpm.pvm.internal.history.HistoryEvent;
@@ -38,6 +38,7 @@
 import org.jbpm.pvm.internal.task.ParticipationImpl;
 import org.jbpm.pvm.internal.task.SwimlaneDefinitionImpl;
 import org.jbpm.pvm.internal.task.SwimlaneImpl;
+import org.jbpm.pvm.internal.task.TaskConstants;
 import org.jbpm.pvm.internal.task.TaskDefinitionImpl;
 import org.jbpm.pvm.internal.task.TaskImpl;
 
@@ -111,36 +112,72 @@
     
     execution.fire(signalName, activity);
 
-    DbSession taskDbSession = EnvironmentImpl
-        .getFromCurrent(DbSession.class);
+    DbSession taskDbSession = EnvironmentImpl .getFromCurrent(DbSession.class);
     TaskImpl task = (TaskImpl) taskDbSession.findTaskByExecution(execution);
     task.setSignalling(false);
     
     Transition transition = null;
     List<Transition> outgoingTransitions = activity.getOutgoingTransitions();
-    if ( (outgoingTransitions!=null)
-         && (!outgoingTransitions.isEmpty())
-       ) {
-      transition = activity.findOutgoingTransition(signalName);
-      if (transition==null) {
-        if (Task.STATE_COMPLETED.equals(signalName)) {
-          if (outgoingTransitions.size()==1) {
+    
+    if ( (outgoingTransitions!=null) && (!outgoingTransitions.isEmpty()) ) {
+      
+      // Lookup the outgoing transition
+      
+      boolean noOutcomeSpecified =TaskConstants.NO_TASK_OUTCOME_SPECIFIED.equals(signalName); 
+      if (noOutcomeSpecified && activity.findOutgoingTransition(signalName) == null) {
+        // When no specific outcome was specified, the unnamed transition
+        // is looked up (name is null). If a null outcome was specifically
+        // used, then the else clause will be used (but the result is the same)
+        // Note: the second part of the if clause is to avoid the siutation
+        // where the user would have chosen the same name as the constant
+        transition = activity.findOutgoingTransition(null); 
+      } else {
+        transition = activity.findOutgoingTransition(signalName);        
+      }
+      
+      // If no transition has been found, we check if we have a special case
+      // in which we can still deduce the outgoing transition
+      
+      if (transition==null) { // no unnamed transition found
+        
+        if (signalName == null) { 
+          
+          // null was explicitely given as outcome
+          throw new JbpmException("No unnamed transitions were found for the task '" + getTaskDefinition().getName() + "'"); 
+          
+        } else if (noOutcomeSpecified) { // Special case: complete(id)
+           
+          if (outgoingTransitions.size() == 1) { // If only 1 transition, take that one
             transition = outgoingTransitions.get(0);
           } else {
-            transition = activity.getDefaultOutgoingTransition();
+            throw new JbpmException("No unnamed transitions were found for the task '" + getTaskDefinition().getName() + "'");                                          
           }
+          
         } else {
-          // if a user specified outcome was provided and it doesn't
-          // match with an outgoing transition name, then an exception is
-          // thrown since this is likely a programmatic error.
-          throw new JbpmException("No outcome named '" + signalName + "' was found."); 
+          // Likely a programmatic error.
+          throw new JbpmException("No transition named '" + signalName + "' was found."); 
         }
+        
       }
+      
       if (transition!=null) {
         execution.take(transition);
       }
+      
     }
   }
+  
+  /**
+   * Checks if the given collection of transitions are all named or not.
+   */
+  private boolean allTransitionsNamed(Collection<Transition> transitions) {
+    for (Transition transition : transitions) {
+      if (transition.getName() == null) {
+        return false;
+      }
+    }
+    return true;
+  }
 
   public TaskDefinitionImpl getTaskDefinition() {
     return taskDefinition;

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/cmd/CompleteTaskCmd.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/cmd/CompleteTaskCmd.java	2009-12-08 03:33:29 UTC (rev 5923)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/cmd/CompleteTaskCmd.java	2009-12-08 13:28:56 UTC (rev 5924)
@@ -35,11 +35,18 @@
   
   protected String taskId;
   protected String outcome;
+  protected boolean outcomeSpecified;
 
   public CompleteTaskCmd(String taskId, String outcome) {
     this.taskId = taskId;
     this.outcome = outcome;
+    this.outcomeSpecified = true;
   }
+  
+  public CompleteTaskCmd(String taskId) {
+    this.taskId = taskId;
+    this.outcomeSpecified = false;
+  }
 
   public Void execute(Environment environment) throws Exception {
     DbSession dbSession = environment.get(DbSession.class);
@@ -54,10 +61,10 @@
       throw new JbpmException("No task with id " + taskId + " was found");
     }
     
-    if (outcome==null) {
+    if (outcomeSpecified) {
+      task.complete(outcome);
+    } else {
       task.complete();
-    } else {
-      task.complete(outcome);
     }
     dbSession.delete(task);
     return null;

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/cmd/GetOutcomes.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/cmd/GetOutcomes.java	2009-12-08 03:33:29 UTC (rev 5923)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/cmd/GetOutcomes.java	2009-12-08 13:28:56 UTC (rev 5924)
@@ -60,8 +60,7 @@
     }
     
     Set<String> outcomes = new HashSet<String>();
-    outcomes.add(Task.STATE_COMPLETED);
-
+    
     ExecutionImpl execution = (task!=null ? task.getExecution() : null);
     ActivityImpl activity = (execution!=null ? execution.getActivity() : null);
     List<Transition> outgoingTransitions = (activity!=null ? activity.getOutgoingTransitions() : null);

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/svc/TaskServiceImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/svc/TaskServiceImpl.java	2009-12-08 03:33:29 UTC (rev 5923)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/svc/TaskServiceImpl.java	2009-12-08 13:28:56 UTC (rev 5924)
@@ -85,7 +85,7 @@
   }
 
   public void completeTask(String taskId) {
-    commandService.execute(new CompleteTaskCmd(taskId, null));
+    commandService.execute(new CompleteTaskCmd(taskId));
   }
   
   public void completeTask(String taskId, Map<String, Object> variables) {

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/task/TaskImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/task/TaskImpl.java	2009-12-08 03:33:29 UTC (rev 5923)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/task/TaskImpl.java	2009-12-08 13:28:56 UTC (rev 5924)
@@ -181,10 +181,10 @@
   }
 
   // completion ///////////////////////////////////////////////////////////////
-
+  
   public void complete() {
-    complete(Task.STATE_COMPLETED);
-  }
+    complete(TaskConstants.NO_TASK_OUTCOME_SPECIFIED);
+  } 
 
   public void complete(String outcome) {
     historyTaskComplete(outcome);

Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/task/TaskCompletionTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/task/TaskCompletionTest.java	2009-12-08 03:33:29 UTC (rev 5923)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/task/TaskCompletionTest.java	2009-12-08 13:28:56 UTC (rev 5924)
@@ -53,14 +53,6 @@
     "  <end name='theEnd' />" +
     "</process>";
   
-  public void testCompletionWithNoOutcome() {
-    Ids ids = deployAndStartProcessInstance();
-    taskService.completeTask(ids.taskId);
-    assertExecutionInOneOrMoreActivitiesActive(ids.processInstanceId, "stateOne", "stateTwo");
-    assertNoOpenTasks(ids.processInstanceId);
-    assertHistoryTaskCreated(ids.processInstanceId, null);
-  }
-  
   public void testCompletionWithNullOrEmptyId() {
     try {
       taskService.completeTask(null);
@@ -116,7 +108,7 @@
     Ids ids = deployAndStartProcessInstance();
     Map<String, Object> vars = new HashMap<String, Object>();
     vars.put("testVar", "testValue");
-    taskService.completeTask(ids.taskId, vars);
+    taskService.completeTask(ids.taskId, "one",vars);
     
     assertEquals("testValue", executionService.getVariable(ids.processInstanceId, "testVar"));
     assertNoOpenTasks(ids.processInstanceId);

Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/task/TaskOutcomesTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/task/TaskOutcomesTest.java	2009-12-08 03:33:29 UTC (rev 5923)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/task/TaskOutcomesTest.java	2009-12-08 13:28:56 UTC (rev 5924)
@@ -34,240 +34,387 @@
  * @author Tom Baeyens
  */
 public class TaskOutcomesTest extends JbpmTestCase {
-
-  public void testTaskSingleUnnamedTransition() {
-    deployJpdlXmlString(
-      "<process name='UnnamedTransition'>" +
-      "  <start>" +
-      "    <transition to='review' />" +
-      "  </start>" +
-      "  <task name='review' " +
-      "        assignee='johndoe'>" +
-      "    <transition to='wait' />" +
-      "  </task>" +
-      "  <state name='wait'/>" +
-      "</process>"
-    );
+  
+  private static final String UNNAMED_TRANSITION_PROCESS_NAME = "UnnamedTransition";
+  
+  private static final String UNNAMED_TRANSITION_PROCESS =
+    "<process name='" + UNNAMED_TRANSITION_PROCESS_NAME +"'>" +
+    "  <start>" +
+    "    <transition to='review' />" +
+    "  </start>" +
+    "  <task name='review' " +
+    "        assignee='johndoe'>" +
+    "    <transition to='wait' />" +
+    "  </task>" +
+    "  <state name='wait'/>" +
+    "</process>";
+  
+  private static final String NAMED_TRANSITION_PROCESS_NAME = "NamedTransition";
+  
+  private static final String NAMED_TRANSITION_PROCESS =
+    "<process name='" +  NAMED_TRANSITION_PROCESS_NAME +"'>" +
+    "  <start>" +
+    "    <transition to='review' />" +
+    "  </start>" +
+    "  <task name='review' " +
+    "        assignee='johndoe'>" +
+    "    <transition name='theOneAndOnly' to='wait' />" +
+    "  </task>" +
+    "  <state name='wait'/>" +
+    "</process>";
+  
+  private static final String NO_TRANSITION_PROCESS_NAME = "NoTransition";
+  
+  private static final String NO_TRANSITION_PROCESS = 
+    "<process name='" + NO_TRANSITION_PROCESS_NAME + "'>" +
+    "  <start>" +
+    "    <transition to='review' />" +
+    "  </start>" +
+    "  <task name='review' " +
+    "        assignee='johndoe'>" +
+    "  </task>" +
+    "  <state name='wait'/>" +
+    "</process>";
+  
+  private static final String MULTIPLE_NAMED_TRANSITIONS_PROCESS_NAME = "MultipleTransitions";
+  
+  private static final String MULTIPLE_NAMED_TRANSITIONS_PROCESS = 
+    "<process name='" + MULTIPLE_NAMED_TRANSITIONS_PROCESS_NAME + "'>" +
+    "  <start>" +
+    "    <transition to='review' />" +
+    "  </start>" +
+    "  <task name='review' " +
+    "        assignee='johndoe'>" +
+    "    <transition name='left' to='wait1' />" +
+    "    <transition name='middle' to='wait2' />" +
+    "    <transition name='right' to='wait3' />" +
+    "  </task>" +
+    "  <state name='wait1'/>" +
+    "  <state name='wait2'/>" +
+    "  <state name='wait3'/>" +
+    "</process>";
+  
+  private static final String MULTIPLE_NOT_ALL_NAMED_TRANSITIONS_PROCESS_NAME = "MultipleTransitionsWithUnnamed";
+  
+  private static final String MULTIPLE_NOT_ALL_NAMED_TRANSITIONS_PROCESS = 
+    "<process name='" + MULTIPLE_NOT_ALL_NAMED_TRANSITIONS_PROCESS_NAME + "'>" +
+    "  <start>" +
+    "    <transition to='review' />" +
+    "  </start>" +
+    "  <task name='review' " +
+    "        assignee='johndoe'>" +
+    "    <transition name='left' to='wait1' />" +
+    "    <transition to='wait2' />" +
+    "    <transition name='right' to='wait3' />" +
+    "  </task>" +
+    "  <state name='wait1'/>" +
+    "  <state name='wait2'/>" +
+    "  <state name='wait3'/>" +
+    "</process>";
+  
+  
+  public void testGetOutcomesNoTransition() {
+    deployJpdlXmlString(NO_TRANSITION_PROCESS);
+    executionService.startProcessInstanceByKey(NO_TRANSITION_PROCESS_NAME);
     
-    ProcessInstance processInstance = executionService.startProcessInstanceByKey("UnnamedTransition");
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
+    Set<String> outcomes = taskService.getOutcomes(task.getId());
     
-    Task task = taskService
-      .createTaskQuery()
-      .assignee("johndoe")
-      .uniqueResult();
-    
-    taskService.completeTask(task.getId());
-    
-    processInstance = executionService.findProcessInstanceById(processInstance.getId());
-    
-    assertNotNull(processInstance.findActiveExecutionIn("wait"));
+    Set<String> expectedOutcomes = new HashSet<String>();
+    assertEquals(expectedOutcomes, outcomes);
   }
 
-  public void testTaskTakeSingleNamedTransition() {
-    deployJpdlXmlString(
-      "<process name='NamedTransition'>" +
-      "  <start>" +
-      "    <transition to='review' />" +
-      "  </start>" +
-      "  <task name='review' " +
-      "        assignee='johndoe'>" +
-      "    <transition name='theOneAndOnly' to='wait' />" +
-      "  </task>" +
-      "  <state name='wait'/>" +
-      "</process>"
-    );
+  public void testGetOutcomesSingleUnnamedTransition() {
+    deployJpdlXmlString(UNNAMED_TRANSITION_PROCESS);
+    executionService.startProcessInstanceByKey(UNNAMED_TRANSITION_PROCESS_NAME);
     
-    ProcessInstance processInstance = executionService.startProcessInstanceByKey("NamedTransition");
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
     
-    Task task = taskService
-      .createTaskQuery()
-      .assignee("johndoe")
-      .uniqueResult();
+    Set<String> outcomes = taskService.getOutcomes(task.getId());
+    Set<String> expectedOutcomes = new HashSet<String>();
+    expectedOutcomes.add(null);
     
-    taskService.completeTask(task.getId());
-    
-    processInstance = executionService.findProcessInstanceById(processInstance.getId());
-    
-    assertNotNull(processInstance.findActiveExecutionIn("wait"));
+    assertEquals(expectedOutcomes, outcomes);
   }
 
-  public void testTaskTakeSingleNamedTransitionWithMatchingOutcome() {
-    deployJpdlXmlString(
-      "<process name='MatchingOutdome'>" +
-      "  <start>" +
-      "    <transition to='review' />" +
-      "  </start>" +
-      "  <task name='review' " +
-      "        assignee='johndoe'>" +
-      "    <transition name='theOneAndOnly' to='wait' />" +
-      "  </task>" +
-      "  <state name='wait'/>" +
-      "</process>"
-    );
+  public void testGetOutcomesSingleNamedTransition() {
+    deployJpdlXmlString(NAMED_TRANSITION_PROCESS);
+    executionService.startProcessInstanceByKey(NAMED_TRANSITION_PROCESS_NAME);
     
-    ProcessInstance processInstance = executionService.startProcessInstanceByKey("MatchingOutdome");
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
+    Set<String> outcomes = taskService.getOutcomes(task.getId());
     
-    Task task = taskService
-      .createTaskQuery()
-      .assignee("johndoe")
-      .uniqueResult();
+    Set<String> expectedOutcomes = new HashSet<String>();
+    expectedOutcomes.add("theOneAndOnly");
     
-    taskService.completeTask(task.getId(), "theOneAndOnly");
-    
-    processInstance = executionService.findProcessInstanceById(processInstance.getId());
-    
-    assertNotNull(processInstance.findActiveExecutionIn("wait"));
+    assertEquals(expectedOutcomes, outcomes);
   }
 
-  public void testTaskTakeSingleNamedTransitionWithUnmatchingOutcome() {
-    deployJpdlXmlString(
-      "<process name='UnmatchingOutcome'>" +
-      "  <start>" +
-      "    <transition to='review' />" +
-      "  </start>" +
-      "  <task name='review' " +
-      "        assignee='johndoe'>" +
-      "    <transition to='wait' />" +
-      "  </task>" +
-      "  <state name='wait'/>" +
-      "</process>"
-    );
+  public void testGetOutcomesMultipleTransitionsAllNamed() {
+    deployJpdlXmlString(MULTIPLE_NAMED_TRANSITIONS_PROCESS);
+    executionService.startProcessInstanceByKey(MULTIPLE_NAMED_TRANSITIONS_PROCESS_NAME);
     
-    ProcessInstance processInstance = executionService.startProcessInstanceByKey("UnmatchingOutcome");
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
+    Set<String> outcomes = taskService.getOutcomes(task.getId());
     
-    Task task = taskService
-      .createTaskQuery()
-      .assignee("johndoe")
-      .uniqueResult();
+    Set<String> expectedOutcomes = new HashSet<String>();
+    expectedOutcomes.add("left");
+    expectedOutcomes.add("right");
+    expectedOutcomes.add("middle");
     
-    try {
-      taskService.completeTask(task.getId(), "Refused");
-      fail();
-    } catch (JbpmException e) {
-      // exception should be thrown
-    }
-    
+    assertEquals(expectedOutcomes, outcomes);
   }
-
-  public void testGetOutcomesNoTransition() {
-    deployJpdlXmlString(
-      "<process name='UnmatchingOutcome'>" +
-      "  <start>" +
-      "    <transition to='review' />" +
-      "  </start>" +
-      "  <task name='review' " +
-      "        assignee='johndoe'>" +
-      "  </task>" +
-      "  <state name='wait'/>" +
-      "</process>"
-    );
+  
+  public void testGetOutcomesMultipleTransitionsNotAllNamed() {
+    deployJpdlXmlString(MULTIPLE_NOT_ALL_NAMED_TRANSITIONS_PROCESS);
+    executionService.startProcessInstanceByKey(MULTIPLE_NOT_ALL_NAMED_TRANSITIONS_PROCESS_NAME);
     
-    ProcessInstance processInstance = executionService.startProcessInstanceByKey("UnmatchingOutcome");
-    
-    Task task = taskService
-      .createTaskQuery()
-      .assignee("johndoe")
-      .uniqueResult();
-    
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
     Set<String> outcomes = taskService.getOutcomes(task.getId());
     
     Set<String> expectedOutcomes = new HashSet<String>();
-    expectedOutcomes.add(Task.STATE_COMPLETED);
+    expectedOutcomes.add("left");
+    expectedOutcomes.add(null);
+    expectedOutcomes.add("right");
     
     assertEquals(expectedOutcomes, outcomes);
   }
 
-  public void testGetOutcomesSingleUnnamedTransition() {
-    deployJpdlXmlString(
-      "<process name='UnmatchingOutcome'>" +
-      "  <start>" +
-      "    <transition to='review' />" +
-      "  </start>" +
-      "  <task name='review' " +
-      "        assignee='johndoe'>" +
-      "    <transition to='wait' />" +
-      "  </task>" +
-      "  <state name='wait'/>" +
-      "</process>"
-    );
+  /**
+   * If a  task has one outgoing transition without a name then
+   * taskService.completeTask(taskId) will take that outgoing transition
+   */
+  public void testCompleteTaskWithOneUnnamedTransitionById() {
+    deployJpdlXmlString(UNNAMED_TRANSITION_PROCESS);  
+    ProcessInstance processInstance = executionService.startProcessInstanceByKey(UNNAMED_TRANSITION_PROCESS_NAME);
     
-    ProcessInstance processInstance = executionService.startProcessInstanceByKey("UnmatchingOutcome");
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
+    taskService.completeTask(task.getId());
     
-    Task task = taskService
-      .createTaskQuery()
-      .assignee("johndoe")
-      .uniqueResult();
+    processInstance = executionService.findProcessInstanceById(processInstance.getId());
+    assertNotNull(processInstance.findActiveExecutionIn("wait"));
+  }
+  
+  /**
+   * If a  task has one outgoing transition without a name then
+   * taskService.completeTask(taskId, null) will take that outgoing transition 
+   */
+  public void testCompleteTaskWithOneUnnamedTransitionByIdAndNullTransition() {
+    deployJpdlXmlString(UNNAMED_TRANSITION_PROCESS);  
+    ProcessInstance processInstance = executionService.startProcessInstanceByKey(UNNAMED_TRANSITION_PROCESS_NAME);
     
-    Set<String> outcomes = taskService.getOutcomes(task.getId());
+    Task task = taskService.createTaskQuery().assignee("johndoe") .uniqueResult();
+    taskService.completeTask(task.getId(), (String) null);
     
-    Set<String> expectedOutcomes = new HashSet<String>();
-    expectedOutcomes.add(Task.STATE_COMPLETED);
-    expectedOutcomes.add(null);
+    processInstance = executionService.findProcessInstanceById(processInstance.getId());
+    assertNotNull(processInstance.findActiveExecutionIn("wait"));
+  }
+  
+  /**
+   * If a  task has one outgoing transition without a name then
+   * taskService.completeTask(taskId, "anyvalue") will result in an exception 
+   */
+  public void testCompleteTaskWithOneUnnamedTransitionByIdAndWrongTransition() {
+    deployJpdlXmlString(UNNAMED_TRANSITION_PROCESS);  
+    executionService.startProcessInstanceByKey(UNNAMED_TRANSITION_PROCESS_NAME);
     
-    assertEquals(expectedOutcomes, outcomes);
+    Task task = taskService.createTaskQuery().assignee("johndoe") .uniqueResult();
+    try {
+      taskService.completeTask(task.getId(), "anyValue");
+      fail();
+    } catch (JbpmException e) {
+      // Exception is expected
+      e.printStackTrace();
+    }
+    assertNotNull("After completion with an invalid outcome, the task should remain unchanged",
+            taskService.createTaskQuery().assignee("johndoe") .uniqueResult());
   }
 
-  public void testGetOutcomesSingleNamedTransition() {
-    deployJpdlXmlString(
-      "<process name='UnmatchingOutcome'>" +
-      "  <start>" +
-      "    <transition to='review' />" +
-      "  </start>" +
-      "  <task name='review' " +
-      "        assignee='johndoe'>" +
-      "    <transition name='toedeloe' to='wait' />" +
-      "  </task>" +
-      "  <state name='wait'/>" +
-      "</process>"
-    );
+  /**
+   * If a task has one named transition, then taskService.completeTask(id)
+   * will take that transition since there is only one.
+   */
+  public void testCompleteTaskWithSingleNamedTransitionById() {
+    deployJpdlXmlString(NAMED_TRANSITION_PROCESS);
+    ProcessInstance processInstance = executionService.startProcessInstanceByKey(NAMED_TRANSITION_PROCESS_NAME);
     
-    ProcessInstance processInstance = executionService.startProcessInstanceByKey("UnmatchingOutcome");
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
+
+    taskService.completeTask(task.getId());
+    processInstance = executionService.findProcessInstanceById(processInstance.getId());
+    assertNotNull(processInstance.findActiveExecutionIn("wait")); 
+  }
+  
+  /**
+   * If a task has one named transition, then taskService.completeTask(id, null)
+   * will result in an exception since there is no unnamed transition.
+   */
+  public void testCompleteTaskWithSingleNamedTransitionByIdAndNullTransition() {
+    deployJpdlXmlString(NAMED_TRANSITION_PROCESS);
+    executionService.startProcessInstanceByKey(NAMED_TRANSITION_PROCESS_NAME);
     
-    Task task = taskService
-      .createTaskQuery()
-      .assignee("johndoe")
-      .uniqueResult();
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
+    try {
+      taskService.completeTask(task.getId(), (String) null);
+      fail();
+    } catch(JbpmException e) {
+      // Exception is expected
+    }
+    assertNotNull(taskService.createTaskQuery().assignee("johndoe").uniqueResult());
+  }
+  
+  /**
+   * If a task has one named transition, then 
+   * taskService.completeTask(taskId, "anyvalue") will result in an exception 
+   */
+  public void testCompleteTaskWithSingleNamedTransitionByIdAndWrongTransition() {
+    deployJpdlXmlString(NAMED_TRANSITION_PROCESS);
+    executionService.startProcessInstanceByKey(NAMED_TRANSITION_PROCESS_NAME);
     
-    Set<String> outcomes = taskService.getOutcomes(task.getId());
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
+
+    try {
+      taskService.completeTask(task.getId(), "anyValue");
+      fail();
+    } catch (JbpmException e) {
+      // Exception is expected
+    } 
+    assertNotNull("After completion with an invalid outcome, the task should remain unchanged",
+            taskService.createTaskQuery().assignee("johndoe") .uniqueResult());
+  }
+ 
+  public void testCompleteTaskWithSingleNamedTransitionByIdAndTransition() {
+    deployJpdlXmlString(NAMED_TRANSITION_PROCESS);
+    ProcessInstance processInstance = executionService.startProcessInstanceByKey(NAMED_TRANSITION_PROCESS_NAME);
     
-    Set<String> expectedOutcomes = new HashSet<String>();
-    expectedOutcomes.add(Task.STATE_COMPLETED);
-    expectedOutcomes.add("toedeloe");
-    
-    assertEquals(expectedOutcomes, outcomes);
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
+    taskService.completeTask(task.getId(), "theOneAndOnly");
+    assertActivityActive(processInstance.getId(), "wait");
   }
 
-  public void testGetOutcomesMultipleTransitions() {
-    deployJpdlXmlString(
-      "<process name='UnmatchingOutcome'>" +
-      "  <start>" +
-      "    <transition to='review' />" +
-      "  </start>" +
-      "  <task name='review' " +
-      "        assignee='johndoe'>" +
-      "    <transition name='left' to='wait' />" +
-      "    <transition name='right' to='wait' />" +
-      "    <transition name='middle' to='wait' />" +
-      "  </task>" +
-      "  <state name='wait'/>" +
-      "</process>"
-    );
+  /**
+   * If a task has multiple outgoing transitions (but not all are named), then
+   * taskService.completeTask(taskId) will take the transition without a name 
+   */
+  public void testCompleteTaskWithMultipleTransitionsNotAllNamedById() {
+    deployJpdlXmlString(MULTIPLE_NOT_ALL_NAMED_TRANSITIONS_PROCESS);
+    ProcessInstance processInstance = executionService.startProcessInstanceByKey(MULTIPLE_NOT_ALL_NAMED_TRANSITIONS_PROCESS_NAME);
     
-    ProcessInstance processInstance = executionService.startProcessInstanceByKey("UnmatchingOutcome");
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult(); 
+    taskService.completeTask(task.getId());
+    assertActivityActive(processInstance.getId(), "wait2");
+  }
+  
+  /**
+   * If a task has multiple outgoing transitions (but not all are named), then
+   * taskService.completeTask(taskId, null) will take the transition without a name 
+   */
+  public void testCompleteTaskWithMultipleTransitionsNotAllNamedByIdAndNullTransition() {
+    deployJpdlXmlString(MULTIPLE_NOT_ALL_NAMED_TRANSITIONS_PROCESS);
+    ProcessInstance processInstance = executionService.startProcessInstanceByKey(MULTIPLE_NOT_ALL_NAMED_TRANSITIONS_PROCESS_NAME);
     
-    Task task = taskService
-      .createTaskQuery()
-      .assignee("johndoe")
-      .uniqueResult();
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult(); 
+    taskService.completeTask(task.getId(), (String) null);
+    assertActivityActive(processInstance.getId(), "wait2");
+  }
+  
+  /**
+   * If a task has multiple outgoing transitions (but not all are named), then
+   * taskService.completeTask(taskId, "anyvalue") will result in an exception 
+   */
+  public void testCompleteTaskWithMultipleTransitionsNotAllNamedByIdAndWrongTransition() {
+    deployJpdlXmlString(MULTIPLE_NOT_ALL_NAMED_TRANSITIONS_PROCESS);
+    executionService.startProcessInstanceByKey(MULTIPLE_NOT_ALL_NAMED_TRANSITIONS_PROCESS_NAME);
     
-    Set<String> outcomes = taskService.getOutcomes(task.getId());
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult(); 
     
-    Set<String> expectedOutcomes = new HashSet<String>();
-    expectedOutcomes.add(Task.STATE_COMPLETED);
-    expectedOutcomes.add("left");
-    expectedOutcomes.add("right");
-    expectedOutcomes.add("middle");
-    
-    assertEquals(expectedOutcomes, outcomes);
+    try {
+      taskService.completeTask(task.getId(), "anyValue");
+      fail();
+    } catch (JbpmException e) {
+      // Exception is expected
+    }
+    assertNotNull("After completion with an invalid outcome, the task should remain unchanged",
+            taskService.createTaskQuery().assignee("johndoe") .uniqueResult());
   }
+  
+  /**
+   * If a task has multiple outgoing transitions (but not all are named), then
+   * taskService.completeTask(taskId, "correctTransition") will take the correct transition
+   */
+  public void testCompleteTaskWithMultipleTransitionsNotAllNamedByIdAndTransition() {
+    deployJpdlXmlString(MULTIPLE_NOT_ALL_NAMED_TRANSITIONS_PROCESS);
+    ProcessInstance processInstance = executionService.startProcessInstanceByKey(MULTIPLE_NOT_ALL_NAMED_TRANSITIONS_PROCESS_NAME);
+
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
+    taskService.completeTask(task.getId(), "right");
+    assertActivityActive(processInstance.getId(), "wait3");
+  }
+  
+  /**
+   * If a task has multiple outgoing transitions (all are named), then
+   * taskService.completeTask(taskId) will result in an exception .
+   */
+  public void testCompleteTaskWithMultipleTransitionsAllNamedById() {
+    deployJpdlXmlString(MULTIPLE_NAMED_TRANSITIONS_PROCESS);
+    executionService.startProcessInstanceByKey(MULTIPLE_NAMED_TRANSITIONS_PROCESS_NAME);
+
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
+    try {
+      taskService.completeTask(task.getId());
+      fail();
+    } catch (JbpmException e) {
+      // Exception is expected
+    }
+  }
+  
+  /**
+   * If a task has multiple outgoing transitions (all are named), then
+   * taskService.completeTask(taskId, null) will result in an exception 
+   */
+  public void testCompleteTaskWithMultipleTransitionsAllNamedByIdAndNullTransition() {
+    deployJpdlXmlString(MULTIPLE_NAMED_TRANSITIONS_PROCESS);
+    executionService.startProcessInstanceByKey(MULTIPLE_NAMED_TRANSITIONS_PROCESS_NAME);
+
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
+    try {
+      taskService.completeTask(task.getId());
+    } catch (JbpmException e) {
+      // Exception is expected
+    }
+    assertNotNull(taskService.createTaskQuery().assignee("johndoe") .uniqueResult());
+  }
+  
+  /**
+   * If a task has multiple outgoing transitions (all are named), then
+   * taskService.completeTask(taskId, "anyvalue") will result in an exception  
+   */
+  public void testCompleteTaskWithMultipleTransitionsAllNamedByIdAndWrongTransition() {
+    deployJpdlXmlString(MULTIPLE_NAMED_TRANSITIONS_PROCESS);
+    executionService.startProcessInstanceByKey(MULTIPLE_NAMED_TRANSITIONS_PROCESS_NAME);
+
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
+    try {
+      taskService.completeTask(task.getId());
+      fail();
+    } catch (JbpmException e) {
+      // Exception is expected
+    }
+    assertNotNull("After completion with an invalid outcome, the task should remain unchanged",
+            taskService.createTaskQuery().assignee("johndoe") .uniqueResult());
+  }
+  
+  /**
+   * If a task has multiple outgoing transitions (all are named), then
+   * taskService.completeTask(taskId, "Accept") will take the 'Accept' transition 
+   */
+  public void testCompleteTaskWithMultipleTransitionsAllNamedByIdAndTransition() {
+    deployJpdlXmlString(MULTIPLE_NAMED_TRANSITIONS_PROCESS);
+    ProcessInstance pi = executionService.startProcessInstanceByKey(MULTIPLE_NAMED_TRANSITIONS_PROCESS_NAME);
+
+    Task task = taskService.createTaskQuery().assignee("johndoe").uniqueResult();
+    taskService.completeTask(task.getId(), "left");
+    assertActivityActive(pi.getId(), "wait1");
+  }
+  
 }

Modified: jbpm4/trunk/modules/test-db/src/test/resources/logging.properties
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/resources/logging.properties	2009-12-08 03:33:29 UTC (rev 5923)
+++ jbpm4/trunk/modules/test-db/src/test/resources/logging.properties	2009-12-08 13:28:56 UTC (rev 5924)
@@ -10,9 +10,9 @@
 # org.jbpm.pvm.internal.util.level=FINE
 
 org.hibernate.level=INFO
-org.hibernate.cfg.SettingsFactory.level=SEVERE
-org.hibernate.cfg.HbmBinder.level=SEVERE
-org.hibernate.SQL.level=FINEST
-org.hibernate.type.level=FINEST
+#org.hibernate.cfg.SettingsFactory.level=SEVERE
+#org.hibernate.cfg.HbmBinder.level=SEVERE
+#org.hibernate.SQL.level=FINEST
+#org.hibernate.type.level=FINEST
 # org.hibernate.tool.hbm2ddl.SchemaExport.level=FINEST
 # org.hibernate.transaction.level=FINEST
\ No newline at end of file

Modified: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Services.xml
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Services.xml	2009-12-08 03:33:29 UTC (rev 5923)
+++ jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Services.xml	2009-12-08 13:28:56 UTC (rev 5924)
@@ -380,8 +380,66 @@
 variables.put(&quot;category&quot;, &quot;small&quot;);
 variables.put(&quot;lires&quot;, 923874893);
 taskService.setVariables(taskId, variables);</programlisting>
-    <para>and complete tasks</para>
-    <programlisting>taskService.completeTask(taskId);</programlisting>
+    <para>The taskService is also used to complete tasks</para>
+    <programlisting>
+taskService.completeTask(taskId);
+taskService.completeTask(taskId, variables);
+taskService.completeTask(taskId, outcome);
+taskService.completeTask(taskId, outcome, variables);
+</programlisting>
+    <para>
+    The API allows to provide a map of variables that will be added as process
+    variables before the task is completed. It is also possible to provide
+    an 'outcome', that will be used to determine which outgoing transition
+    will be chosen. The logic is as follows:
+    </para>
+    <para>
+      <emphasis role="bold">
+      If a task has one outgoing transition without a name then:
+      </emphasis>
+	    <itemizedlist>
+	      <listitem>taskService.getOutcomes() returns a collection that includes one null value</listitem>
+	      <listitem>taskService.completeTask(taskId) will take that outgoing transition</listitem>
+	      <listitem>taskService.completeTask(taskId, null) will take that outgoing transition</listitem>
+	      <listitem>taskService.completeTask(taskId, "anyvalue") will result in an exception</listitem>
+	    </itemizedlist>
+    </para>
+    <para>
+      <emphasis role="bold">
+      If a task has one outgoing transition with a name then: 
+      </emphasis>
+      <itemizedlist>
+        <listitem>gtaskService.etOutcomes() returns a collection that includes only the name of the transition</listitem>
+        <listitem>taskService.completeTask(taskId) will take the single outgoing transition</listitem>
+        <listitem>taskService.completeTask(taskId, null) will will result in an exception (as there is no transition without a name)</listitem>
+        <listitem>taskService.completeTask(taskId, "anyvalue") will result in an exception</listitem>
+        <listitem>taskService.completeTask(taskId, "myName") will take the transition with the given name</listitem>
+      </itemizedlist>
+    </para>
+    <para>
+      <emphasis role="bold">
+      If a task has multiple outgoing transitions. One transition has no a name and the other transition have a name:
+      </emphasis>
+      <itemizedlist>
+        <listitem>taskService.getOutcomes() returns a collection that includes a null value and the names of the other transitions</listitem>
+        <listitem>taskService.completeTask(taskId) will take the transition without a name</listitem>
+        <listitem>taskService.completeTask(taskId, null) will take the transition without a name</listitem>
+        <listitem>taskService.completeTask(taskId, "anyvalue") will result in an exception</listitem>
+        <listitem>taskService.completeTask(taskId, "myName") will take the 'myName' transition</listitem>
+      </itemizedlist>
+    </para>
+    <para>
+      <emphasis role="bold">
+      If a task has multiple outgoing transitions and all of them are uniquely named, then:  
+      </emphasis>
+      <itemizedlist>
+        <listitem>taskService.getOutcomes() returns a collection that includes all the names of all the transitions</listitem>
+        <listitem>taskService.completeTask(taskId) will result in an exception, since there is no transition without a name</listitem>
+        <listitem>taskService.completeTask(taskId, null) will result in an exception, since there is no unnamed transition</listitem>
+        <listitem>taskService.completeTask(taskId, "anyvalue") will result in an exception</listitem>
+        <listitem>taskService.completeTask(taskId, "myName") will take the 'myName' transition</listitem>
+      </itemizedlist>
+    </para>    
     <para>Tasks can also be offered to a set of candidates.  Candidates can be 
     users or groups.  Users can take tasks for which they are a candidate.  Taking 
     a task means that this user will be set as the assignee.  After that, other users 



More information about the jbpm-commits mailing list