[jbpm-commits] JBoss JBPM SVN: r6329 - in jbpm3/branches/jbpm-3.2-soa/modules/core/src: main/java/org/jbpm/graph/node and 4 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Wed May 12 05:43:32 EDT 2010


Author: alex.guizar at jboss.com
Date: 2010-05-12 05:43:32 -0400 (Wed, 12 May 2010)
New Revision: 6329

Modified:
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/DelegationException.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/GraphElement.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Node.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/Decision.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/svc/save/CheckUnpersistableVariablesOperation.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/taskmgmt/exe/TaskMgmtInstance.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jpdl/exe/DecisionHandlerTest.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/scheduler/exe/SchedulerTest.java
Log:
JBPM-1162: ensure decision node selects default transition after decision handler throws exception

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/DelegationException.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/DelegationException.java	2010-05-12 04:10:11 UTC (rev 6328)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/DelegationException.java	2010-05-12 09:43:32 UTC (rev 6329)
@@ -28,17 +28,20 @@
 
   private static final long serialVersionUID = 1L;
 
+  /** @deprecated this execution context may not be in a consistent state */
   protected transient ExecutionContext executionContext;
 
   public DelegationException(String message, Throwable cause) {
     super(message, cause);
   }
 
+  /** @deprecated the given execution context may not be in a consistent state */
   public DelegationException(Throwable cause, ExecutionContext executionContext) {
     super(cause.getMessage(), cause);
     this.executionContext = executionContext;
   }
 
+  /** @deprecated the returned execution context may not be in a consistent state */
   public ExecutionContext getExecutionContext() {
     return executionContext;
   }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/GraphElement.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/GraphElement.java	2010-05-12 04:10:11 UTC (rev 6328)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/GraphElement.java	2010-05-12 09:43:32 UTC (rev 6329)
@@ -157,13 +157,16 @@
   }
 
   public void reorderExceptionHandler(int oldIndex, int newIndex) {
-    if (exceptionHandlers != null && Math.min(oldIndex, newIndex) >= 0
+    if (exceptionHandlers != null
+      && Math.min(oldIndex, newIndex) >= 0
       && Math.max(oldIndex, newIndex) < exceptionHandlers.size()) {
       Object o = exceptionHandlers.remove(oldIndex);
       exceptionHandlers.add(newIndex, o);
     }
     else {
-      throw new IndexOutOfBoundsException("could not move element from " + oldIndex + " to "
+      throw new IndexOutOfBoundsException("could not move element from "
+        + oldIndex
+        + " to "
         + newIndex);
     }
   }
@@ -324,14 +327,14 @@
   }
 
   /**
-   * throws an ActionException if no applicable exception handler is found. An ExceptionHandler
-   * is searched for in this graph element and then recursively up the parent hierarchy. If an
-   * exception handler is found, it is applied. If the exception handler does not throw an
-   * exception, the exception is considered handled. Otherwise the search for an applicable
-   * exception handler continues where it left of with the newly thrown exception.
+   * looks for an {@linkplain ExceptionHandler exception handler} in this graph element and then
+   * recursively up the parent hierarchy. If an exception handler is found, it is applied. If
+   * the exception handler does not rethrow, the exception is considered handled. Otherwise the
+   * rethrown exception is propagated up the parent hierarchy.
+   * 
+   * @throws DelegationException if no applicable exception handler is found
    */
-  public void raiseException(Throwable exception, ExecutionContext executionContext)
-    throws DelegationException {
+  public void raiseException(Throwable exception, ExecutionContext executionContext) {
     if (isAbleToHandleExceptions(executionContext)) {
       try {
         ExceptionHandler exceptionHandler = findExceptionHandler(exception);
@@ -358,7 +361,7 @@
 
     // if exception was not handled, throw delegation exception to client
     throw exception instanceof JbpmException ? (JbpmException) exception
-      : new DelegationException(exception, executionContext);
+      : new DelegationException("no applicable exception handler found", exception);
   }
 
   /**

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Node.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Node.java	2010-05-12 04:10:11 UTC (rev 6328)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Node.java	2010-05-12 09:43:32 UTC (rev 6329)
@@ -272,14 +272,14 @@
    * is the default leaving transition.
    */
   public Transition getDefaultLeavingTransition() {
-    if (leavingTransitions != null) {
+    if (leavingTransitions != null && !leavingTransitions.isEmpty()) {
       // select the first unconditional transition
       for (Iterator i = leavingTransitions.iterator(); i.hasNext();) {
         Transition transition = (Transition) i.next();
         if (transition.getCondition() == null) return transition;
       }
       // there is no unconditional transition, just pick the first one
-      if (!leavingTransitions.isEmpty()) return (Transition) leavingTransitions.get(0);
+      return (Transition) leavingTransitions.get(0);
     }
     else if (superState != null) {
       return superState.getDefaultLeavingTransition();

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/Decision.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/Decision.java	2010-05-12 04:10:11 UTC (rev 6328)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/Decision.java	2010-05-12 09:43:32 UTC (rev 6329)
@@ -91,19 +91,11 @@
 
       Transition transition = null;
       if (decisionDelegation != null) {
-        DecisionHandler decisionHandler = (DecisionHandler) decisionDelegation.getInstance();
-        try {
-          String transitionName = decisionHandler.decide(executionContext);
-          transition = getLeavingTransition(transitionName);
-          if (transition == null) {
-            throw new JbpmException("no such transition: " + transitionName);
-          }
-        }
-        catch (Exception e) {
-          raiseException(e, executionContext);
-        }
+        // call decision handler
+        transition = handleDecision(executionContext);
       }
       else if (decisionExpression != null) {
+        // evaluate expression
         String transitionName = (String) JbpmExpressionEvaluator
           .evaluate(decisionExpression, executionContext, String.class);
         transition = getLeavingTransition(transitionName);
@@ -165,6 +157,26 @@
     }
   }
 
+  private Transition handleDecision(ExecutionContext executionContext) {
+    // invoke handler to obtain transition name
+    DecisionHandler decisionHandler = (DecisionHandler) decisionDelegation.getInstance();
+    String transitionName;
+    try {
+      transitionName = decisionHandler.decide(executionContext);
+    }
+    catch (Exception e) {
+      raiseException(e, executionContext);
+      return null;
+    }
+
+    // resolve transition from name
+    Transition transition = getLeavingTransition(transitionName);
+    if (transition == null) {
+      throw new JbpmException("no such transition: " + transitionName);
+    }
+    return transition;
+  }
+
   public List getDecisionConditions() {
     return decisionConditions;
   }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/svc/save/CheckUnpersistableVariablesOperation.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/svc/save/CheckUnpersistableVariablesOperation.java	2010-05-12 04:10:11 UTC (rev 6328)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/svc/save/CheckUnpersistableVariablesOperation.java	2010-05-12 09:43:32 UTC (rev 6329)
@@ -37,31 +37,20 @@
   private static final long serialVersionUID = 1L;
 
   public void save(ProcessInstance processInstance, JbpmContext jbpmContext) {
-    Collection updatedVariableContainers = VariableContainer.getUpdatedVariableContainers(processInstance);
-    if (updatedVariableContainers!=null) {
-
-      // loop over all updated variable containers
-      Iterator iter = updatedVariableContainers.iterator();
-      while (iter.hasNext()) {
-        VariableContainer variableContainer = (VariableContainer) iter.next();
+    Collection variableContainers = processInstance.getContextInstance()
+      .getUpdatedVariableContainers();
+    // iterate over variable containers
+    if (variableContainers != null) {
+      for (Iterator containerIter = variableContainers.iterator(); containerIter.hasNext();) {
+        VariableContainer variableContainer = (VariableContainer) containerIter.next();
         Map variableInstances = variableContainer.getVariableInstances();
-        if (variableInstances!=null) {
-
-          // loop over all variable instances in the container
-          Iterator varInstancesIter = variableInstances.entrySet().iterator();
-          while (varInstancesIter.hasNext()) {
-            Map.Entry entry = (Map.Entry) varInstancesIter.next();
-            String name = (String) entry.getKey();
-            VariableInstance variableInstance = (VariableInstance) entry.getValue();
-
-            // if the variable is of the unpersistable type...  booom!
+        // iterate over variable instances
+        if (variableInstances != null) {
+          for (Iterator instanceIter = variableInstances.values().iterator(); instanceIter.hasNext();) {
+            VariableInstance variableInstance = (VariableInstance) instanceIter.next();
+            // if the variable cannot be persisted... boom!
             if (variableInstance instanceof UnpersistableInstance) {
-              Object value = variableInstance.getValue();
-              if (value!=null) {
-                throw new JbpmException("variable '"+name+"' in '"+variableContainer+"' contains '"+value+"': type '"+value.getClass().getName()+"' is unpersistable according to the jbpm.varmapping.xml configuration");
-              } else {
-                throw new JbpmException("variable '"+name+"' in '"+variableContainer+"' was created with a non persistable value");
-              }
+              throw new JbpmException(variableInstance + " cannot be persisted");
             }
           }
         }
@@ -69,5 +58,4 @@
     }
   }
 
-  // private static Log log = LogFactory.getLog(CheckUnpersistableVariablesOperation.class);
 }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/taskmgmt/exe/TaskMgmtInstance.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/taskmgmt/exe/TaskMgmtInstance.java	2010-05-12 04:10:11 UTC (rev 6328)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/taskmgmt/exe/TaskMgmtInstance.java	2010-05-12 09:43:32 UTC (rev 6329)
@@ -230,17 +230,7 @@
   public void performAssignment(Delegation assignmentDelegation, String actorIdExpression,
     String pooledActorsExpression, Assignable assignable, ExecutionContext executionContext) {
     if (assignmentDelegation != null) {
-      try {
-        performAssignmentDelegation(assignmentDelegation, assignable, executionContext);
-      }
-      catch (Exception e) {
-        GraphElement graphElement = executionContext.getEventSource();
-        if (graphElement == null) {
-          throw e instanceof JbpmException ? (JbpmException) e
-            : new DelegationException(e, executionContext);
-        }
-        graphElement.raiseException(e, executionContext);
-      }
+      performAssignmentDelegation(assignmentDelegation, assignable, executionContext);
     }
     else {
       if (actorIdExpression != null) {
@@ -253,8 +243,8 @@
   }
 
   private void performAssignmentDelegation(Delegation assignmentDelegation,
-    Assignable assignable, ExecutionContext executionContext) throws Exception {
-    ClassLoader surroundingClassLoader = Thread.currentThread().getContextClassLoader();
+    Assignable assignable, ExecutionContext executionContext) {
+    ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
     try {
       // set context class loader correctly for delegation class
       // https://jira.jboss.org/jira/browse/JBPM-1448
@@ -268,15 +258,25 @@
       // invoke the assignment handler
       UserCodeInterceptor userCodeInterceptor = UserCodeInterceptorConfig
         .getUserCodeInterceptor();
-      if (userCodeInterceptor != null) {
-        userCodeInterceptor.executeAssignment(assignmentHandler, assignable, executionContext);
+      try {
+        if (userCodeInterceptor != null) {
+          userCodeInterceptor.executeAssignment(assignmentHandler, assignable, executionContext);
+        }
+        else {
+          assignmentHandler.assign(assignable, executionContext);
+        }
       }
-      else {
-        assignmentHandler.assign(assignable, executionContext);
+      catch (Exception e) {
+        GraphElement eventSource = executionContext.getEventSource();
+        if (eventSource == null) {
+          throw e instanceof JbpmException ? (JbpmException) e
+            : new DelegationException("event source is null", e);
+        }
+        eventSource.raiseException(e, executionContext);
       }
     }
     finally {
-      Thread.currentThread().setContextClassLoader(surroundingClassLoader);
+      Thread.currentThread().setContextClassLoader(contextClassLoader);
     }
   }
 

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jpdl/exe/DecisionHandlerTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jpdl/exe/DecisionHandlerTest.java	2010-05-12 04:10:11 UTC (rev 6328)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jpdl/exe/DecisionHandlerTest.java	2010-05-12 09:43:32 UTC (rev 6329)
@@ -22,6 +22,7 @@
 package org.jbpm.jpdl.exe;
 
 import org.jbpm.AbstractJbpmTestCase;
+import org.jbpm.JbpmException;
 import org.jbpm.graph.def.ProcessDefinition;
 import org.jbpm.graph.exe.ExecutionContext;
 import org.jbpm.graph.exe.ProcessInstance;
@@ -33,51 +34,76 @@
     private static final long serialVersionUID = 1L;
 
     public String decide(ExecutionContext executionContext) {
-      int budget = ((Number)executionContext.getContextInstance().getVariable("budget")).intValue();
-      if (budget>1000) return "important lead";
-      else if (budget>100) return "lead";
-      return "beggars";
+      Number wrapper = (Number) executionContext.getContextInstance().getVariable("budget");
+      int budget = wrapper.intValue();
+      return budget > 1000 ? "important lead" : budget == 777 ? "lucky number"
+        : budget > 100 ? "lead" : "beggars";
     }
   }
 
-  ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
-    "<process-definition>" +
-    "  <start-state>" +
-    "    <transition to='d' />" +
-    "  </start-state>" +
-    "  <decision name='d'>" +
-    "    <handler class='org.jbpm.jpdl.exe.DecisionHandlerTest$LeadEvaluator'/>" +
-    "    <transition name='important lead' to='harras them'/>" +
-    "    <transition name='lead' to='put it in the lead db'/>" +
-    "    <transition name='beggars' to='forget about it'/>" +
-    "  </decision>" +
-    "  <state name='harras them' />" +
-    "  <state name='put it in the lead db' />" +
-    "  <state name='forget about it' />" +
-    "</process-definition>" );
-  
+  ProcessDefinition processDefinition = ProcessDefinition.parseXmlString("<process-definition>"
+    + "  <start-state>"
+    + "    <transition to='d' />"
+    + "  </start-state>"
+    + "  <decision name='d'>"
+    + "    <handler class='org.jbpm.jpdl.exe.DecisionHandlerTest$LeadEvaluator'/>"
+    + "    <transition name='beggars' to='forget about it'/>"
+    + "    <transition name='lead' to='put it in the lead db'/>"
+    + "    <transition name='important lead' to='harass them'/>"
+    + "    <exception-handler exception-class='java.lang.ClassCastException'/>"
+    + "  </decision>"
+    + "  <state name='harass them' />"
+    + "  <state name='put it in the lead db' />"
+    + "  <state name='forget about it' />"
+    + "</process-definition>");
+
   public void testBudgetHignerThenThousand() {
     ProcessInstance processInstance = new ProcessInstance(processDefinition);
     processInstance.getContextInstance().setVariable("budget", new Integer(3500));
     processInstance.signal();
-    
-    assertEquals(processDefinition.getNode("harras them"), processInstance.getRootToken().getNode());
+
+    assertEquals(processDefinition.getNode("harass them"), processInstance.getRootToken()
+      .getNode());
   }
 
   public void testBudgetBetweenHundredAndThousand() {
     ProcessInstance processInstance = new ProcessInstance(processDefinition);
     processInstance.getContextInstance().setVariable("budget", new Integer(350));
     processInstance.signal();
-    
-    assertEquals(processDefinition.getNode("put it in the lead db"), processInstance.getRootToken().getNode());
+
+    assertEquals(processDefinition.getNode("put it in the lead db"), processInstance.getRootToken()
+      .getNode());
   }
 
   public void testSmallBudget() {
     ProcessInstance processInstance = new ProcessInstance(processDefinition);
     processInstance.getContextInstance().setVariable("budget", new Integer(35));
     processInstance.signal();
-    
-    assertEquals(processDefinition.getNode("forget about it"), processInstance.getRootToken().getNode());
+
+    assertEquals(processDefinition.getNode("forget about it"), processInstance.getRootToken()
+      .getNode());
   }
 
+  public void testBadTransitionName() {
+    ProcessInstance processInstance = new ProcessInstance(processDefinition);
+    processInstance.getContextInstance().setVariable("budget", new Integer(777));
+
+    try {
+      processInstance.signal();
+      fail("expected exception");
+    }
+    catch (JbpmException e) {
+      assert e.getMessage().indexOf("lucky number") != -1;
+    }
+  }
+
+  public void testHandledException() {
+    ProcessInstance processInstance = new ProcessInstance(processDefinition);
+    processInstance.getContextInstance().setVariable("budget", "nothing");
+    processInstance.signal();
+
+    // decision node should take default transition
+    assertEquals(processDefinition.getNode("forget about it"), processInstance.getRootToken()
+      .getNode());
+  }
 }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/scheduler/exe/SchedulerTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/scheduler/exe/SchedulerTest.java	2010-05-12 04:10:11 UTC (rev 6328)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/scheduler/exe/SchedulerTest.java	2010-05-12 09:43:32 UTC (rev 6329)
@@ -689,7 +689,9 @@
       processInstance.signal();
     }
     catch (JbpmException je) {
-      assertEquals("improper format of duration '1 demo'", je.getMessage());
+      Throwable cause = je.getCause();
+      assertSame(IllegalArgumentException.class, cause.getClass());
+      assert cause.getMessage().indexOf("1 demo") != -1 : cause;
     }
     finally {
       jbpmContext.close();



More information about the jbpm-commits mailing list