Skip to main content

Data Objects

A data object is a process-level variable with a declared type. It bridges an inline type and the actual runtime value stored in the process instance.

Available in BPMN XML only

These constructs (itemDefinition, dataObject/dataObjectReference, dataStore/dataStoreReference) are parsed only from BPMN 2.0 XML definitions. JSON/YAML process definitions express a subset and cannot declare typed data objects, data stores, or inline types. See the Processes guide for JSON/YAML format limitations.

Two BPMN Elements

BPMN 2.0 uses two elements together:

  • <bpmn:dataObject> — declared inside <bpmn:process>, names the variable and references its type.
  • <bpmn:dataObjectReference> — a positional "sighting" of that variable at a specific point in the flow. Multiple references can point to the same dataObject.
<bpmn:process id="loan-application" isExecutable="true">

<!-- Declare the typed variables -->
<bpmn:dataObject id="ApplicationData" name="application" itemSubjectRef="Applicant" />
<bpmn:dataObject id="StatusData" name="loan_status" itemSubjectRef="LoanStatus" />

<!-- Place them in the flow -->
<bpmn:dataObjectReference id="ApplicationDataRef" dataObjectRef="ApplicationData" />
<bpmn:dataObjectReference id="StatusDataRef" dataObjectRef="StatusData" />

</bpmn:process>

The name attribute of a dataObject becomes the key in instance.variables. In the example above, instance.variables.application is validated against the Applicant type on every write.

Coexistence with Untyped Variables

Typed and untyped variables live together in the same variables map. Only variables declared as dataObject are validated — everything else passes through freely:

# "internal_counter" is not declared as a dataObject — it passes through without validation
curl -X POST https://api.stateway.io/v1/instances \
-H "X-API-Key: sw_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"definition_key": "loan-application",
"variables": {
"application": {
"fullName": "Ana Lima",
"email": "ana@example.com"
},
"internal_counter": 0
}
}'

application is validated against the Applicant schema. internal_counter is stored as-is.

Validation on Write

Whenever a typed variable is written — at instance creation, task completion, or service task output — Stateway validates the value against the declared type before merging it into instance.variables.

Invalid write example:

curl -X POST https://api.stateway.io/v1/instances \
-H "X-API-Key: sw_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"definition_key": "loan-application",
"variables": {
"application": {
"fullName": "A",
"email": "not-an-email"
}
}
}'

Response 400 Bad Request:

{
"error": "ValidationError",
"errors": [
{ "path": "application.fullName", "message": "must NOT have fewer than 2 characters" },
{ "path": "application.email", "message": "must match format \"email\"" }
]
}

The instance is not created. No partial state is written.

dataState — Lifecycle Annotation

Each dataObjectReference optionally carries a dataState attribute. It has no effect on validation or execution — it's an annotation for the human reader:

<bpmn:dataObjectReference
id="ApplicationDataRef_collected"
dataObjectRef="ApplicationData"
dataState="collected" />

<bpmn:dataObjectReference
id="ApplicationDataRef_reviewed"
dataObjectRef="ApplicationData"
dataState="reviewed" />

Using two references for the same dataObject with different states is a BPMN convention for showing lifecycle transitions in the diagram. Both point to the same application variable at runtime.

Collections

When the referenced itemDefinition has isCollection="true", the variable must be a JSON array, and each element is validated individually:

<bpmn:itemDefinition id="Documents" structureRef="stateway:inline" isCollection="true">
<bpmn:extensionElements>
<stateway:schema kind="object"><![CDATA[
{
"type": "object",
"required": ["name", "url"],
"properties": {
"name": { "type": "string" },
"url": { "type": "string", "format": "uri" }
}
}
]]></stateway:schema>
</bpmn:extensionElements>
</bpmn:itemDefinition>

<bpmn:dataObject id="DocListData" name="documents" itemSubjectRef="Documents" />

Writing documents with a non-array value, or with an array element missing name, produces a ValidationError with the array index in the path (e.g., documents[1].url).

When to Use Typed Variables

Use typed dataObjectLeave untyped
Business-critical fields (applicant, amount, status)Temporary working variables
Fields shared across multiple tasksOne-off intermediate values
Enum values with a fixed set of valid optionsInternal counters, flags
Fields received from external systemsDebug/logging metadata

You can introduce typed variables incrementally. Adding a dataObject to an existing process only affects the named variable — everything else continues unchanged.