Multiinstance subprocess and out params mapping

Hello,
I have simple example of subprocess

Imagine process of generating invoices where invoice items are generated as subprocesses.

I have problem with agregating id of items from these subprocesses. I don’t know how to map output variables from subprocess to some kind of list (in parent) or add some listener which has access to variables of ending subprocess and variables of parent process

Sources of processes are below.
Output of execution

Found process definition : invoice-item
generate-invoice-header
	generate-invoice-item [idInvoice:500, idProduct:1, idItem:1]
	generate-invoice-item [idInvoice:500, idProduct:2, idItem:2]
	generate-invoice-item [idInvoice:500, idProduct:3, idItem:3]
summarize [idInvoice:500, invoice-items:[1, 2, 3]] //where is output mapping itemsCollection

Parent DEF

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:flowable="http://flowable.org/bpmn" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">

  <process id="invoice" name="invoice" isExecutable="true">
    <startEvent id="start"></startEvent>
    <scriptTask id="generate-invoice-header" name="generate-invoice-header" flowable:async="true" scriptFormat="groovy" >
     <script>
     	println 'generate-invoice-header'
     	execution.setVariable('idInvoice', 500);
     	execution.setVariable('invoice-items', [1,2,3]);
     </script>
    </scriptTask>


   	 <callActivity id="generate-items" name="generate-items" calledElement="invoice-item" flowable:async="false">
   	  <extensionElements>
        <flowable:in source="item" target="idProduct"></flowable:in>
        <flowable:in source="idInvoice" target="idInvoice"></flowable:in>
        <flowable:out source="idItem" target="itemsCollection"></flowable:out>
        </extensionElements>
      <multiInstanceLoopCharacteristics  isSequential="true" flowable:collection="invoice-items" flowable:elementVariable="item">
      </multiInstanceLoopCharacteristics>
      </callActivity>

      <scriptTask id="summarize" name="summarize" flowable:async="true" scriptFormat="groovy" >
     <script>
     println 'summarize '+execution.getVariables()
     </script>
    </scriptTask>
    <endEvent id="end">
    </endEvent>

    <sequenceFlow id="flow1" sourceRef="start" targetRef="generate-invoice-header"></sequenceFlow>
    <sequenceFlow id="flow2" sourceRef="generate-invoice-header" targetRef="generate-items"></sequenceFlow>
    <sequenceFlow id="flow3" sourceRef="generate-items" targetRef="summarize"></sequenceFlow>
    <sequenceFlow id="flow5" sourceRef="summarize" targetRef="end"></sequenceFlow>
  </process>
</definitions>

Child Def

<?xml version="1.0" encoding="UTF-8"?>
<definitions
	xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
	xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
	xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
	xmlns:flowable="http://flowable.org/bpmn"
	typeLanguage="http://www.w3.org/2001/XMLSchema"
	expressionLanguage="http://www.w3.org/1999/XPath"
	targetNamespace="http://www.flowable.org/processdef">
	<process id="invoice-item" name="invoice-item"
		isExecutable="true">
		<startEvent id="start" />

		 <scriptTask id="generate-invoice-item" name="generate-invoice-item" flowable:async="true" scriptFormat="groovy" >
     <script>
     	execution.setVariable('idItem', execution.getVariable('idProduct')); //aka subprocess response to collect in parent
     	println '	generate-invoice-item '+execution.getVariables()
     </script>
    </scriptTask>
	<endEvent id="end" >
		</endEvent>

		<sequenceFlow sourceRef="start" targetRef="generate-invoice-item" />
		<sequenceFlow sourceRef="generate-invoice-item" targetRef="end" />
	</process>

</definitions>

Hey @MirekSz,

Your question comes in the right time. This is actually is a problem for multi instance executions since the beginning of the project and is a problem for all of the similar BPMN engines out there.

The good thing is that starting from Flowable 6.6.1 this will no longer be a problem and it would be extremely easy to perform variable aggregation of multi instances into one single array node.

We are planning to write some blog posts about this and explaining how you can use it. For now you can have a look at the PR where this functionality was added.

In order to make it work now you will have to use a multi instance sub process with a service task after the CallActivity, store the output variables in the execution locally, then in the service task add them to an array node on the execution. You’ll have to use a sequential multi instance for this to work properly.

Cheers,
Filip

1 Like