beekum
April 22, 2026, 3:09pm
1
Hi, I have Operaton set up as a standalone application (using the Docker images) where Java applications execute tasks using the Java library org.operaton.bpm:operaton-external-task-client@2.0.0.
I am trying to introduce multi-instances (expanded sub processes) into the BPMN model, but have been unable to create variables in the multi-instance scope from the external tasks. How would I go about this? Ideally, the solution doesn’t require the external task implementation to know whether it is in multi-instance scope or not (because that seems to be a detail of the model, not the task)
I’ve been using a minimal BPMN model (see below). The script task creates a list of numbers (execution.setVariable("list", S("[1, 2, 3]"));). The multi-instance loops over this collection with element variable number. The first external task creates a copy of number called copy with the handler
(externalTask, externalTaskService) -> {
Map<String, Object> variables = externalTask.getAllVariables();
variables.put("copy", variables.get("number"));
externalTaskService.complete(externalTask, variables);
}
I’ve tried different versions of this, such as passing the copy variable in a localVariables map or by settings outputs in the BPMN model, but all result in a single copy variable on process instance level instead of a variable per multi-instance branch:
Any suggestions?
Hi @beekum , thanks for reaching out!
I have some time on my hands to look into this, but it would be easier for me if you could share your BPMN model here as an attachment, so I’m sure that I’m comparing the same things, would that be possible?
I hope I understood your usecase correctly, I hope this helps (not sure, as you already mentioned localVariables):
client.subscribe("create-copy-of-numbers")
.lockDuration(20_000)
.handler((externalTask, externalTaskService) -> {
Object number = externalTask.getVariable("number");
Map<String, Object> localVariables = new HashMap<>();
localVariables.put("copy", number);
externalTaskService.complete(externalTask, null, localVariables);
})
.open();
externalTaskService.complete can be overloaded, the third parameter contains variables which should explicitly be written to the local scope.
If I run this external Task Service, I can see the following in the Cockpit:
The Scope for the variable “number” is “For Each Number”, the variable exists once per parallel execution
beekum
April 23, 2026, 8:21am
4
Thanks for taking a look @javahippie .
The “number” variable is indeed created within the local scope by the multi-instance. The handler for the “create-copy-of-numbers” topic creates a new variable called “copy”. How can I get “copy” to be added to the local scope?
The overload of externalTaskService.completeon its own doesn’t seem to add “copy” to a scope that still exists when the MI branch has moved to “Uninmplemented task”. When I add an output to the task “Create Copy of Numbers” to map ${copy} to “copy”, the variable is added in the process instance scope.
The editor only allows me to upload images, so here’s the XML of the model:
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0n66yia" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.30.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.22.0">
<bpmn:process id="multi-instance-process" name="multi-instance-process" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_02c0ab1</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_02c0ab1" sourceRef="StartEvent_1" targetRef="Activity_04usbxa" />
<bpmn:sequenceFlow id="Flow_0ge8wzs" sourceRef="Activity_04usbxa" targetRef="for-each-number-mi" />
<bpmn:subProcess id="for-each-number-mi" name="For each number">
<bpmn:incoming>Flow_0ge8wzs</bpmn:incoming>
<bpmn:outgoing>Flow_09m808m</bpmn:outgoing>
<bpmn:multiInstanceLoopCharacteristics camunda:collection="${list.elements()}" camunda:elementVariable="number" />
<bpmn:startEvent id="Event_1ckvrre">
<bpmn:outgoing>Flow_11235kc</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_11235kc" sourceRef="Event_1ckvrre" targetRef="copyNumber" />
<bpmn:sequenceFlow id="Flow_0ko70r6" sourceRef="copyNumber" targetRef="Activity_0jwavk4" />
<bpmn:serviceTask id="Activity_0jwavk4" name="Unimplemented task" camunda:type="external" camunda:topic="unimplemented">
<bpmn:incoming>Flow_0ko70r6</bpmn:incoming>
<bpmn:outgoing>Flow_0fc2x6v</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:serviceTask id="copyNumber" name="Create copy of number" camunda:type="external" camunda:topic="copyNumber">
<bpmn:extensionElements>
<camunda:inputOutput>
<camunda:outputParameter name="copy">${copy}</camunda:outputParameter>
</camunda:inputOutput>
</bpmn:extensionElements>
<bpmn:incoming>Flow_11235kc</bpmn:incoming>
<bpmn:outgoing>Flow_0ko70r6</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:intermediateThrowEvent id="Event_0s7loqu">
<bpmn:incoming>Flow_0fc2x6v</bpmn:incoming>
</bpmn:intermediateThrowEvent>
<bpmn:sequenceFlow id="Flow_0fc2x6v" sourceRef="Activity_0jwavk4" targetRef="Event_0s7loqu" />
</bpmn:subProcess>
<bpmn:scriptTask id="Activity_04usbxa" name="Create list of numbers" scriptFormat="javascript">
<bpmn:incoming>Flow_02c0ab1</bpmn:incoming>
<bpmn:outgoing>Flow_0ge8wzs</bpmn:outgoing>
<bpmn:script>const variable = S("[1, 2, 3]");
execution.setVariable("list", variable);</bpmn:script>
</bpmn:scriptTask>
<bpmn:intermediateThrowEvent id="Event_0wd8fxe">
<bpmn:incoming>Flow_09m808m</bpmn:incoming>
</bpmn:intermediateThrowEvent>
<bpmn:sequenceFlow id="Flow_09m808m" sourceRef="for-each-number-mi" targetRef="Event_0wd8fxe" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="multi-instance-process">
<bpmndi:BPMNShape id="StartEvent_1_di" bpmnElement="StartEvent_1">
<dc:Bounds x="182" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0qaubh3_di" bpmnElement="for-each-number-mi" isExpanded="true">
<dc:Bounds x="450" y="80" width="530" height="200" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1ckvrre_di" bpmnElement="Event_1ckvrre">
<dc:Bounds x="490.3333333333333" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0d3hscw_di" bpmnElement="Activity_0jwavk4">
<dc:Bounds x="740" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0lp5a2k_di" bpmnElement="copyNumber">
<dc:Bounds x="580" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0s7loqu_di" bpmnElement="Event_0s7loqu">
<dc:Bounds x="902" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_11235kc_di" bpmnElement="Flow_11235kc">
<di:waypoint x="526" y="180" />
<di:waypoint x="580" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0ko70r6_di" bpmnElement="Flow_0ko70r6">
<di:waypoint x="680" y="180" />
<di:waypoint x="740" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0fc2x6v_di" bpmnElement="Flow_0fc2x6v">
<di:waypoint x="840" y="180" />
<di:waypoint x="902" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Activity_0essq4c_di" bpmnElement="Activity_04usbxa">
<dc:Bounds x="270" y="140" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0wd8fxe_di" bpmnElement="Event_0wd8fxe">
<dc:Bounds x="1062" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_02c0ab1_di" bpmnElement="Flow_02c0ab1">
<di:waypoint x="218" y="180" />
<di:waypoint x="270" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0ge8wzs_di" bpmnElement="Flow_0ge8wzs">
<di:waypoint x="370" y="180" />
<di:waypoint x="450" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_09m808m_di" bpmnElement="Flow_09m808m">
<di:waypoint x="980" y="180" />
<di:waypoint x="1062" y="180" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>