Skip to content

Data Exchange between BPMN Processes

A BPMN collaboration diagram shows how two or more business entities interact (see the article BPMN Collaboration Diagram). Each entity gets its own pool. A pool stands for a major participant, often a separate organization (see BPMN Swimlane (Pool and Lane)).

Message flows connect pools. A message flow can never link elements inside the same pool. That makes it the connector between pools. Each message has exactly one sender and one recipient.

Events carry the signal. A process can have one or more message start events. Deploying the process creates a message subscription for each one. An intermediate message catch event also creates a subscription when the process reaches it, so the instance waits there until the message arrives.

Data stores hold shared data. A data object shows the reader which data an activity needs or produces. A data store is the shared place where data is kept. One process writes data into it. Another process reads it later. This follows the Shared Database style: applications integrate by keeping their data in one common database (see Shared Database). The store decouples writer and reader. Neither needs to know when the other runs.

A timer can start the reader. A timer start event creates a new process instance each time the timer fires. It needs a date or a cycle definition, and deployment schedules it. This lets the reader check the store on a schedule, in a polling style (see Polling Consumer).

Tool support varies. Camunda supports data stores and data objects for modeling only, not for execution. A diagram can show the store, but the engine will not read or write it for you.

An online shop has two pools. The “Order intake” pool saves each new order to an orders store. A separate “Reporting” pool starts every night from a timer start event. It reads the orders store and builds a sales summary. Intake never calls Reporting. If Intake needs to tell Reporting something directly, it sends a message across the pools.

A shared store keeps writer and reader independent, but it needs a schema that suits every user. Designing that shared schema is one of the biggest difficulties of the Shared Database style. Messages are different: each goes from one sender to one recipient, so they fit a signal for a single receiver. Because Camunda treats stores as modeling-only, the diagram documents the data exchange but does not run it.

Two pools: the writer saves data to a store, and a timer-started reader process reads it.

Diagram source
<?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:di="http://www.omg.org/spec/DD/20100524/DI" id="defs" targetNamespace="http://example.com/bpmn">
<bpmn:dataStore id="ordersStore" name="Orders store" />
<bpmn:collaboration id="collab">
<bpmn:participant id="poolWriter" name="Order intake" processRef="writerProcess" />
<bpmn:participant id="poolReader" name="Reporting" processRef="readerProcess" />
</bpmn:collaboration>
<bpmn:process id="writerProcess" isExecutable="false">
<bpmn:dataStoreReference id="storeRef" name="Orders store" dataStoreRef="ordersStore" />
<bpmn:startEvent id="wStart" name="Order received">
<bpmn:outgoing>w1</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:task id="wTask" name="Save order">
<bpmn:incoming>w1</bpmn:incoming>
<bpmn:outgoing>w2</bpmn:outgoing>
<bpmn:dataOutputAssociation id="wOut">
<bpmn:targetRef>storeRef</bpmn:targetRef>
</bpmn:dataOutputAssociation>
</bpmn:task>
<bpmn:endEvent id="wEnd" name="Order saved">
<bpmn:incoming>w2</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="w1" sourceRef="wStart" targetRef="wTask" />
<bpmn:sequenceFlow id="w2" sourceRef="wTask" targetRef="wEnd" />
</bpmn:process>
<bpmn:process id="readerProcess" isExecutable="false">
<bpmn:dataStoreReference id="storeRef2" name="Orders store" dataStoreRef="ordersStore" />
<bpmn:startEvent id="rStart" name="Every night">
<bpmn:outgoing>r1</bpmn:outgoing>
<bpmn:timerEventDefinition id="rTimer" />
</bpmn:startEvent>
<bpmn:task id="rTask" name="Build sales summary">
<bpmn:incoming>r1</bpmn:incoming>
<bpmn:outgoing>r2</bpmn:outgoing>
<bpmn:dataInputAssociation id="rIn">
<bpmn:sourceRef>storeRef2</bpmn:sourceRef>
</bpmn:dataInputAssociation>
</bpmn:task>
<bpmn:endEvent id="rEnd" name="Summary ready">
<bpmn:incoming>r2</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="r1" sourceRef="rStart" targetRef="rTask" />
<bpmn:sequenceFlow id="r2" sourceRef="rTask" targetRef="rEnd" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_collab">
<bpmndi:BPMNPlane id="BPMNPlane_collab" bpmnElement="collab">
<bpmndi:BPMNShape id="BPMNShape_poolWriter" bpmnElement="poolWriter" isHorizontal="true">
<dc:Bounds x="80" y="130" width="482" height="160" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_poolReader" bpmnElement="poolReader" isHorizontal="true">
<dc:Bounds x="80" y="420" width="482" height="160" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_wStart" bpmnElement="wStart">
<dc:Bounds x="150" y="192" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="138" y="233" width="60" height="28" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_wTask" bpmnElement="wTask">
<dc:Bounds x="286" y="170" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_wEnd" bpmnElement="wEnd">
<dc:Bounds x="486" y="192" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="464" y="233" width="80" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_storeRef" bpmnElement="storeRef">
<dc:Bounds x="311" y="80" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="293" y="61" width="87" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_w1" bpmnElement="w1">
<di:waypoint x="186" y="210" />
<di:waypoint x="286" y="210" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_w2" bpmnElement="w2">
<di:waypoint x="386" y="210" />
<di:waypoint x="486" y="210" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_wOut" bpmnElement="wOut">
<di:waypoint x="336" y="170" />
<di:waypoint x="336" y="130" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="BPMNShape_rStart" bpmnElement="rStart">
<dc:Bounds x="150" y="482" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="128" y="523" width="80" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_rTask" bpmnElement="rTask">
<dc:Bounds x="286" y="460" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_rEnd" bpmnElement="rEnd">
<dc:Bounds x="486" y="482" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="474" y="523" width="61" height="28" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_storeRef2" bpmnElement="storeRef2">
<dc:Bounds x="311" y="370" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="293" y="351" width="87" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_r1" bpmnElement="r1">
<di:waypoint x="186" y="500" />
<di:waypoint x="286" y="500" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_r2" bpmnElement="r2">
<di:waypoint x="386" y="500" />
<di:waypoint x="486" y="500" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_rIn" bpmnElement="rIn">
<di:waypoint x="336" y="420" />
<di:waypoint x="336" y="460" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
  • Processes run by different participants are modeled in separate pools, and message flows (not links inside one pool) connect them.
  • Each message has a single sender and a single recipient.
  • A reader process that polls a shared store has a timer start event with a date or cycle definition.
  • The shared schema of a data store used by several processes is designed and documented.
  • Where Camunda is used, the document states that data stores and data objects are modeling-only and not executed.