Skip to main content

Migrating from Form Schema

If your process definitions already use stateway:FormSchema on userTask elements, you don't need to change anything. Stateway is fully backward-compatible.

How the Two Coexist

ConfigurationValidation AuthorityForm Rendering
Only stateway:FormSchema (legacy)formSchema JSON SchemaformSchema fields
Only ioSpecificationioSpecification types via itemDefinitionAuto-generated from dataInput types
Both presentioSpecification (type authority)formSchema as UI decoration

Incremental Migration

Add ioSpecification to a single task at a time without touching the rest of the process:

Before (legacy — only stateway:FormSchema):

<bpmn:userTask id="review" name="Review Application">
<bpmn:extensionElements>
<stateway:FormSchema>{"type":"object","properties":{"decision":{"type":"string","title":"Decision"}}}</stateway:FormSchema>
</bpmn:extensionElements>
</bpmn:userTask>

After (typed, with formSchema as a UI hint):

<!-- At <bpmn:definitions> level: -->
<bpmn:itemDefinition id="LoanStatus" structureRef="stateway:inline">
<bpmn:extensionElements>
<stateway:schema kind="enum"><![CDATA[
{ "type": "string", "enum": ["approved", "rejected", "more_info"] }
]]></stateway:schema>
</bpmn:extensionElements>
</bpmn:itemDefinition>

<!-- In the process: -->
<bpmn:userTask id="review" name="Review Application">
<bpmn:ioSpecification>
<bpmn:dataOutput id="out_decision" name="decision" itemSubjectRef="LoanStatus" />
<bpmn:outputSet>
<bpmn:dataOutputRefs>out_decision</bpmn:dataOutputRefs>
</bpmn:outputSet>
</bpmn:ioSpecification>

<!-- formSchema kept as UI hint: widget choice, label, help text -->
<bpmn:extensionElements>
<stateway:FormSchema>{"type":"object","properties":{"decision":{"type":"string","enum":["approved","rejected","more_info"],"title":"Decision"}}}</stateway:FormSchema>
</bpmn:extensionElements>
</bpmn:userTask>

The ioSpecification validates the submitted value against the LoanStatus enum. The formSchema tells the Frontend Gateway to render a dropdown with those options and a specific label.

Automatic Form Generation

When a task has ioSpecification but no formSchema, the Frontend Gateway generates a form automatically from the dataInput declarations and their itemDefinition schemas:

itemDefinition typeGenerated widget
xsd:stringText input
xsd:decimal / xsd:intNumber input
xsd:booleanCheckbox
xsd:date / xsd:dateTimeDate picker
Inline enumDropdown with enum values
Inline objectOne field group per property (recursively)
Inline isCollectionRepeating field group

You can remove formSchema entirely once you've added ioSpecification, and forms will still render correctly.

Validation Priority

If both are present and they conflict (e.g., formSchema allows any string but ioSpecification restricts to an enum), the ioSpecification wins for validation. The formSchema is UI metadata only in this case.

No Migration Deadline

There is no deprecation timeline for formSchema. Existing definitions continue to work indefinitely without changes. Migrate at your own pace, one task at a time.

info

Adding ioSpecification to a task that previously only had formSchema is a behavioral change: the engine now enforces types on completion. Test with invalid payloads before deploying to production to confirm error paths behave as expected.