Looking for some community feedback:
I have a scenario I came across where you have a list you want to iterate through and find all of the matches.
The pattern that quickly hacked together was to use DMN to find all of the matches in a Collect List usage of the DMN.
Mocked Example:
You have a list of “Systems” and you want to get the list of the Managers of those Systems.
Notice that you could have the same “Managers” of different systems. In this scenario lets assume that only unique hits are supported, but we could also have scenarios where we have more than 1 manager per system and thus use Collect List Hit policy.
The complexity came as (far as i can tell), you cannot inject a “array” into a DMN. Example: Send a array of ["System 1", "System 3"]
, and have the DMN tell you the outputs/hits. The expected/desired output would have been ["user 1", "user 3"]
.
A scenario where this pattern seemed to be desired is when you want to get a list that use in a Multi-Instance sub-process. Example Scenario: A user fills out a form for System Access to various computers system in the organization. That form has a listing of “Systems” that are checked. This creates a array of “systems”. And lets assume that each system has a different “Manager”/user who needs to review the request.
something like:
So in this example a Form would have been filled out and the DMN determines which users need to review the request and the desired action is that each Manager of the systems would get their own Task to complete with the relevant information.
I believe I could have structured the DMN differently to support the desired list, but it did not seem manageable. Assume that we have hundreds of rules in the DMN with System to User mappings. The cleaner the file the better.
So in this BPMN I did the following:
I generate a fictional array in the Script task with Groovy:
def collection = ["System 1", "System 3"]
execution.setVariable("collection", collection)
def jsonValue = S('{ "values":[] }')
execution.setVariable("combinedResult", jsonValue)
The jsonValue is used a placeholder to append DMN outputs as we will see next.
I created a DMN and set it to Multi-Instance Sequential (basically iterate over the collection of “Systems” that would have been checked off in the Start Form).
The DMN Map Decision Result is set for SingleResult
I then used a listener to grab the DMN Output at the end of each execution of the DMN instances.
var combinedResult = execution.getVariable("combinedResult");
var dmn_output = execution.getVariable("dmn_output")["user"];
combinedResult.prop("values").append(dmn_output)
execution.setVariable("combinedResult", combinedResult)
I used SPIN to append the DMN instances output to the “combinedResult” variable. So basically after each instance of the DMN execution, the combinedResult variable would be appended with the DMN’s output value.
I then set the Multi-Instance sub-process to use the array elements as a collection:
I created simple placeholder User Tasks that were assigned to the same user (for testing purposes) but appended the Element Variable value into the Task Name.
so we get:
So overall:
This pattern allowed me to use DMN in basically a “Loop Over a Array of Values and combined DMN instance outputs into a single collection”.
What are peoples thoughts? A better more simple way? I had found reference to this: How can pass multiple values to input variable in request body - #4 by thorben, but it seemed more complicated to manage.
Other than the Execution Listener, there is not “sneaky” usage going on.
Files for anyone that wants to test:
array_test.dmn (1.4 KB)
array-input-dmn.bpmn (7.7 KB)