Best way to access a Business Rule Task's decisionResult when using the default ResultList mapping

I’m building processes that leverage DMN Decision Tables. To integrate DMN into the BPMN process, I’m using a Business Rule Task.

I’m letting Camunda default to its predefined mapper which sets the result variable to a resultList, of type List<Map<String, Object>>.

How can I access the values of this resultList: List<Map<String,Object>> from within another DMN XML so it can be used as input?

It’s very easy to reference process variables if they are of primitive types (e.g., String, Integer) but I can’t seem to figure this out for a complex data structure like List<Map<String, Object>.

For example, I can reference the guests variable that is populated by the user when they fill in a User Task form like this:

 <input id="guests" label="How many guests" camunda:inputVariable="guests">
    <inputExpression id="LiteralExpression_0h5951a" typeRef="integer">
        <text>guests</text>
    </inputExpression>
</input>

What is the equivalent to access the first, or really any value in this list?

In the documentation I’ve found code examples that are giving me hints of how I could accomplish it but can’t seem to get it right.

In the example below (which I found in the documentation I linked above), decisionResult is a List<Map<String, Object>>, they get the first element of the List and then to read the Maps value they use .reason as key:

      <camunda:outputParameter name="reason">
        ${decisionResult.getSingleResult().reason}
      </camunda:outputParameter>

I tried this but it doesn’t seem to work.

If you use the mapping to a result variable like this in your business rule task

<bpmn:businessRuleTask id="DecisionABC" camunda:resultVariable="result" camunda:decisionRef="DecisionABC" />

Then the result variable will afterwards be of type List<Map<String, Object>> and could be accessed as follows in following activities of the process:

${result[0].reason}

You can also define output variable mappings as you did, but if you have multiple results in your decision it would look like this:

${decisionResult.getResultList()[0].reason}

The variable decisionResult is of type DmnDecisionResult. the JavaDoc for that class is here:
https://docs.camunda.org/javadoc/camunda-bpm-platform/7.19/org/camunda/bpm/dmn/engine/DmnDecisionResult

1 Like

Hey,

Just to be clear, in my BusinessRuleTask tag, I’m not specifying a value for camunda:mapDecisionResult which as I understand, means Camunda will default to resultList which as you confirmed will be a variable of type List<Map<String, Object>>.

I like this behavior because it allows me to have Decision Tables with more than one output.

What I would like to do is to be able to read those result variables.

This is how I have my stuff set up:

I have two Decision tables: Decide on Dish and Decide on Drink, both have their own Business Rule Task in which I don’t specify a value for camunda:mapDecisionResult so they output stuff into a List<Map<String, Object>>.

I can confirm this configuration is working as expected cause if I read the process variables after execution I can see something like this:

        "dishDecision": {
            "name": "dishDecision",
            "dataType": "OBJECT",
            "stringValue": "[{desiredDish=Stew}]"
        },
        "drinkDecision": {
            "name": "drinkDecision",
            "dataType": "OBJECT",
            "stringValue": "[{alternateDrink=Water, desiredDrink=Gin}]"
        }

Now, I want to take it one step further and use the dishDecision value, which is: [{desiredDish=Stew}] as input in my Decide on Drink DMN.

I tried your suggested:

${result[0].reason}

Of course with the variable names I used but Camunda complains it can’t find them. Where and how do I reference the other DMN’s output so I can use it as input?

Here’s my Decide on Drink DMN XML for context:

  <decision id="dish" name="Drink" camunda:historyTimeToLive="P180D">
    <decisionTable id="decisionTable">
      <input id="season" label="Season" camunda:inputVariable="season">
        <inputExpression id="inputExpression1" typeRef="string">
          <text>season</text>
        </inputExpression>
      </input>
      <input id="guests" label="How many guests" camunda:inputVariable="guests">
        <inputExpression id="LiteralExpression_0h5951a" typeRef="integer">
          <text>guests</text>
        </inputExpression>
      </input>
      <output id="output1" label="drink" name="desiredDrink" typeRef="string" />
      <output id="OutputClause_1cew6yl" label="alternateDrink" name="alternateDrink" typeRef="string" />
      <rule id="row-129502239-1">
        <description></description>
        <inputEntry id="UnaryTests_0e47zyl">
          <text>"Fall"</text>
        </inputEntry>
        <inputEntry id="UnaryTests_1132erh">
          <text>&gt;=8</text>
        </inputEntry>
        <outputEntry id="LiteralExpression_0wv4x30">
          <text>"Gin"</text>
        </outputEntry>
        <outputEntry id="LiteralExpression_0tq0xgs">
          <text>"Water"</text>
        </outputEntry>
      </rule>
      <rule id="row-129502239-2">
        <inputEntry id="UnaryTests_0iwabd6">
          <text>"Spring"</text>
        </inputEntry>
        <inputEntry id="UnaryTests_10qbns7">
          <text>&lt;= 8</text>
        </inputEntry>
        <outputEntry id="LiteralExpression_0ysj59c">
          <text>"Rum"</text>
        </outputEntry>
        <outputEntry id="LiteralExpression_0v3q9og">
          <text>"Coke"</text>
        </outputEntry>
      </rule>
    </decisionTable>
  </decision>
</definitions>

I’m not totally certain if I understand you correctly. One way to access those variables would be by using an input variable mapping for your business rule task. So e.g.

    <bpmn:businessRuleTask id="Activity_0srtoz9" name="Decide Drink" camunda:resultVariable="drinkDecision" camunda:decisionRef="drink">
      <bpmn:extensionElements>
        <camunda:inputOutput>
          <camunda:inputParameter name="firstDish">${dishDecision[0].desiredDish}</camunda:inputParameter>
        </camunda:inputOutput>
      </bpmn:extensionElements>
      <bpmn:incoming>Flow_0cvrl1x</bpmn:incoming>
      <bpmn:outgoing>Flow_06uy2dp</bpmn:outgoing>
    </bpmn:businessRuleTask>

Now you can access the variable firstDish inside your DMN table.
If you want to directly access your resultList variable in the DMN you can do it as follows:

      <input id="InputClause_10fhcxi" label="Dish">
        <inputExpression id="LiteralExpression_0b21u7j" typeRef="string">
          <text>dishDecision[1].desiredDish</text>
        </inputExpression>
      </input>

The index here for FEEL expressions is 1 based.

1 Like

I ended up going with the second approach which I did tried before but the key for it to get it to work was that you said:

The index here for FEEL expressions is 1 based

I was doing everything right, except that I was hitting index 0 instead of 1!

Thank you so much for such a thorough and complete answer to my question,
Daniel

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.