Uploaded image for project: 'jBPM'
  1. jBPM
  2. JBPM-1169

NPE in org.jbpm.graph.node.Decision.execute() when using transitions with null conditions migrated from JBPM 3.0

    XMLWordPrintable

Details

    • Bug
    • Resolution: Obsolete
    • Major
    • None
    • jBPM 3.2.2
    • Runtime Engine
    • None
    • Low

    Description

      A NullPointerException is raised by org.jbpm.graph.node.Decision.execute(ExecutionContext) if the table JBPM_DECISIONCONDITIONS row has null EXPRESSION_ field.
      The following conditions must meet:
      1) initially, the user has a JBPM database in version 3.0 and a decision with conditional transitions
      2) one of the conditional condition is cleared, which leads to setting the field EXPRESSION_ to null in the database
      3) the JBPM database migrated from 3.0 schema to version 3.2
      Note: the JBPM 3.2 database is (almost?) the same as the version 3.1, so the bug should also occur in version 3.1 (not tested).

      The exception is:

      Exception in thread "main" org.jbpm.graph.def.DelegationException
      at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:387)
      at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:378)
      at org.jbpm.graph.node.Decision.execute(Decision.java:148)
      at org.jbpm.graph.def.Node.enter(Node.java:319)
      at org.jbpm.graph.def.Transition.take(Transition.java:151)
      at org.jbpm.graph.def.Node.leave(Node.java:394)
      at org.jbpm.graph.node.StartState.leave(StartState.java:70)
      at org.jbpm.graph.exe.Token.signal(Token.java:195)
      at org.jbpm.graph.exe.Token.signal(Token.java:140)
      at org.jbpm.graph.exe.ProcessInstance.signal(ProcessInstance.java:271)
      at com.sample.TestDecisionNPE.main(TestDecisionNPE.java:53)
      Caused by: java.lang.NullPointerException
      at org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator.translateExpressionToDollars(JbpmExpressionEvaluator.java:52)
      at org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator.evaluate(JbpmExpressionEvaluator.java:38)
      at org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator.evaluate(JbpmExpressionEvaluator.java:30)
      at org.jbpm.graph.node.Decision.execute(Decision.java:110)
      ... 8 more

      This bug can be tested using the following test case:

      package com.sample;

      import java.lang.reflect.Field;
      import java.util.ArrayList;
      import java.util.List;

      import org.jbpm.graph.def.ProcessDefinition;
      import org.jbpm.graph.def.Transition;
      import org.jbpm.graph.exe.ProcessInstance;
      import org.jbpm.graph.node.Decision;
      import org.jbpm.graph.node.DecisionCondition;

      public class TestDecisionNPE {
      public static final void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException{
      ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
      "<process-definition>" +
      " <start-state>" +
      " <transition to='d' />" +
      " </start-state>" +
      " <decision name='d'>" +
      " <transition name='one' to='a'>" +
      " <condition>#

      {a == 1}

      </condition>" +
      " </transition>" +
      " <transition name='two' to='b'>" +
      " <condition>#

      {a == 2}

      </condition>" +
      " </transition>" +
      " <transition name='three' to='c'>" +
      " <condition>#

      {a == 3}

      </condition>" +
      " </transition>" +
      " </decision>" +
      " <state name='a' />" +
      " <state name='b' />" +
      " <state name='c' />" +
      "</process-definition>");

      // start-state.
      ProcessInstance processInstance = new ProcessInstance(processDefinition);

      // Update a transition decision condition as if it was on the old format
      // by setting the condition to null (i.e. no condition).
      // Build a decisionConditions list (emulates an old database from
      // JBPM 3.0, obsolete JBPM_DECISIONCONDITION table).
      List decision_conditions = new ArrayList();
      decision_conditions.add(new DecisionCondition("one", null));
      Decision decision = (Decision) processDefinition.getNode("d");
      Field field = decision.getClass().getDeclaredField("decisionConditions");
      field.setAccessible(true);
      field.set(decision, decision_conditions);

      // fire the transition (as we have an old decision condition set, org.jbpm.graph.node.Decision#execute will raise a NullPointerException).
      processInstance.signal();
      }
      }

      The bug can be corrected using the following code in the execute() method (added lines ends with "JK") :

      // backwards compatible mode based on separate DecisionCondition's
      Iterator iter = decisionConditions.iterator();
      while (iter.hasNext() && (transition==null)) {
      DecisionCondition decisionCondition = (DecisionCondition) iter.next();
      if (decisionCondition.expression!=null) {//JK
      Object result = JbpmExpressionEvaluator.evaluate(decisionCondition.getExpression(), executionContext);
      if (Boolean.TRUE.equals(result)) {
      if (transition!=null)

      { transition.removeConditionEnforcement(); }

      String transitionName = decisionCondition.getTransitionName();
      transition = getLeavingTransition(transitionName);
      }
      } else

      {//JK String transitionName = decisionCondition.getTransitionName();//JK transition = getLeavingTransition(transitionName);//JK }

      //JK

      Note that the JBPM 3.0.4 version had this check against null values.

      Attachments

        Activity

          People

            tdiesler@redhat.com Thomas Diesler
            jkronegg_jira Julien Kronegg (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Time Tracking

                Estimated:
                Original Estimate - 6 weeks
                6w
                Remaining:
                Remaining Estimate - 6 weeks
                6w
                Logged:
                Time Spent - Not Specified
                Not Specified