BPMN2
Comparisons
The Business Process Model and Notation (BPMN) defines a flowchart-based DSL for workflows. It is maintained by the Object Management Group (OMG). The latest BPMN version is 2.0.2, published in 2014.
BPMN2 defines a graphical notation to specify workflows. This notation can then be shared between tooling and organizations. The graphical notation is translated into XML, which then can be used for runtime execution.
For this comparison, we will compare the Serverless Workflow language with the graphical representation of BPMN2, and not its underlying XML representation. The BPMN2 XML is very difficult to understand, quite large for even the smallest workflows, and often not portable between runtimes. It makes more sense to use its portable graphical notation for comparisons.
Serverless Workflow is a declarative workflow language, represented with JSON or YAML. It currently does not define a graphical notation. However, it can be graphically represented using different flowcharting techniques such as UML activity diagrams. The Serverless Workflow Java SDK as well as its VSCode Extension provide means to generate SVG diagrams based on the workflow JSON/YAML.
Note when reading provided examples
The BPMN2 graphical notation does not provide details about data inputs/outputs, mapping, and transformation. BPMN2 does provide graphical representation for things such as Data Objects. However, most of the examples available do not use them. Execution semantics such as task and event properties are also not visual. For this reason, the event, function, retry, and data mapping defined in the associated Serverless Workflow YAML are assumed.
Examples
Simple File Processor
id: processfile
name: Process File Workflow
version: '1.0.0'
specVersion: '0.8'
start: Process File
states:
- name: Process File
type: operation
actions:
- functionRef: processFile
end: true
functions:
- name: processFile
operation: file://myservice.json#process
Process Application
id: processapplication
name: Process Application
version: '1.0.0'
specVersion: '0.8'
start: ProcessNewApplication
states:
- name: ProcessNewApplication
type: event
onEvents:
- eventRefs:
- ApplicationReceivedEvent
actions:
- functionRef: processApplicationFunction
- functionRef: acceptApplicantFunction
- functionRef: depositFeesFunction
end:
produceEvents:
- eventRef: NotifyApplicantEvent
functions:
- name: processApplicationFunction
operation: file://myservice.json#process
- name: acceptApplicantFunction
operation: file://myservice.json#accept
- name: depositFeesFunction
operation: file://myservice.json#deposit
events:
- name: ApplicationReceivedEvent
type: application
source: "/applications/new"
- name: NotifyApplicantEvent
type: notifications
source: "/applicants/notify"
Compensation
id: simplecompensation
name: Simple Compensation
version: '1.0.0'
specVersion: '0.8'
start: Step 1
states:
- name: Step 1
type: operation
actions:
- functionRef: step1function
compensatedBy: Cancel Step 1
transition: Step 2
- name: Step 2
type: operation
actions:
- functionRef: step2function
transition: OK?
- name: OK?
type: switch
dataConditions:
- name: 'yes'
condition: ${ .outcome | .ok == "yes" }
end: true
- name: 'no'
condition: ${ .outcome | .ok == "no" }
end:
compensate: true
- name: Cancel Step 1
type: operation
usedForCompensation: true
actions:
- functionRef: undostep1
functions:
- name: step1function
operation: file://myservice.json#step1
- name: step2function
operation: file://myservice.json#step2
- name: undostep1function
operation: file://myservice.json#undostep1
Error Handling With Retries
---
id: errorwithretries
name: Error Handling With Retries Workflow
version: '1.0.0'
specVersion: '0.8'
start: Make Coffee
states:
- name: Make Coffee
type: operation
actions:
- functionRef: makeCoffee
transition: Add Milk
- name: Add Milk
type: operation
actions:
- functionRef: addMilk
retryRef: noMilkRetries
retryableErrors:
- D'oh! No more Milk!
onErrors:
- errorRef: D'oh! No more Milk!
end: true
transition: Drink Coffee
- name: Drink Coffee
type: operation
actions:
- functionRef: drinkCoffee
end: true
retries:
- name: noMilkRetries
delay: PT1M
maxAttempts: 10
errors:
- name: D'oh! No more Milk!
code: '123'
functions:
- name: makeCoffee
operation: file://myservice.json#make
- name: addMilk
operation: file://myservice.json#add
- name: drinkCoffee
operation: file://myservice.json#drink
Process Execution Timeout
id: executiontimeout
name: Execution Timeout Workflow
version: '1.0.0'
specVersion: '0.8'
start: Purchase Parts
timeouts:
workflowExecTimeout:
duration: PT7D
interrupt: true
runBefore: Handle timeout
states:
- name: Purchase Parts
type: operation
actions:
- functionRef: purchasePartsFunction
transition: Unpack Parts
- name: Unpack Parts
type: operation
actions:
- functionRef: unpackPartsFunction
end: true
- name: Handle timeout
type: operation
actions:
- functionRef: handleTimeoutFunction
functions:
- name: purchasePartsFunction
operation: file://myservice.json#purchase
- name: unpackPartsFunction
operation: file://myservice.json#unpack
- name: handleTimeoutFunction
operation: file://myservice.json#handle
Multiple Instance Subprocess
id: foreachWorkflow
name: ForEach State Workflow
version: '1.0.0'
specVersion: '0.8'
start: ForEachItem
states:
- name: ForEachItem
type: foreach
inputCollection: "${ .inputsArray }"
iterationParam: "${ .inputItem }"
outputCollection: "${ .outputsArray }"
actions:
- subFlowRef: doSomethingAndWaitForMessage
end: true
Note: We did not include the
dosomethingandwaitformessage
workflow in this example, which would just include a starting "operation" state transitioning to an "event" state which waits for the needed event.
Loop Subprocess
id: subflowloop
name: SubFlow Loop Workflow
version: '1.0.0'
specVersion: '0.8'
start: SubflowRepeat
states:
- name: SubflowRepeat
type: operation
actions:
- functionRef: checkAndReplyToEmail
actionDataFilter:
fromStateData: ${ .someInput }
toStateData: ${ .someInput }
stateDataFilter:
output: ${ .maxChecks -= 1 }
transition: CheckCount
- name: CheckCount
type: switch
dataConditions:
- condition: ${ .maxChecks > 0 }
transition: SubflowRepeat
defaultCondition:
end: true
This workflow assumes that the input to the workflow includes a maxChecks attribute set to an integer value.
Note: We did not include the
checkAndReplyToEmail
workflow in this example, which would include the control-flow logic to check email and make a decision to reply to it or wait an hour.
Approve Report
id: approvereport
name: Approve Report Workflow
version: '1.0.0'
specVersion: '0.8'
start: Approve Report
states:
- name: Approve Report
type: callback
action:
functionRef: managerDecideOnReport
eventRef: ReportDecisionMadeEvent
transition: Evaluate Report Decision
- name: Evaluate Report Decision
type: switch
dataConditions:
- name: Approve
condition: "${ .decision | .approved == true }"
end: true
- name: Reject
condition: "${ .decision | .approved != true }"
transition: Update Report
- name: Update Report
type: callback
action:
functionRef: workerUpdateReport
eventRef: ReportUpdatedEvent
transition: Approve Report
events:
- name: ReportDecisionMadeEvent
type: report.decisions
source: reports/decision
- name: ReportUpdatedEvent
type: report.updated
source: reports/updated
functions:
- name: managerDecideOnReport
operation: file://myservice.json#managerapproval
- name: workerUpdateReport
operation: file://myservice.json#workerupdate
Note: Human interactions during workflow execution in Serverless Workflow is handled via its Callback state.
Event Based Decision
id: eventdecision
name: Event Decision workflow
version: '1.0.0'
specVersion: '0.8'
start: A
states:
- name: A
type: operation
actions:
- subFlowRef: asubflowid
transition: Event Decision
- name: Event Decision
type: switch
eventConditions:
- eventRef: EventB
transition: B
- eventRef: EventC
transition: C
- name: B
type: operation
actions:
- name: doSomething
functionRef: doSomethingFunction
end: true
- name: C
type: operation
actions:
- name: doSomething
functionRef: doSomethingFunction
end: true
events:
- name: EventB
type: my.events.b
source: "/events/+"
- name: EventC
type: my.events.c
source: "/events/+"
functions:
- name: doSomethingFunction
operation: file://myservice.json#dosomething
Last updated