BPM End-to-End Walkthrough

BPMN Designer covers the designer's nodes and canvas; BPM Workflows covers how processes relate to Commands. This page connects those concepts to an example you can actually run: the OSS workflow-demo plugin.

workflow-demo is an open-source plugin (namespace wd) that is config-only plus a small backend jar. It uses a single "leave approval" business flow to exercise every part of BPM:

  • Designer — the wd_leave_approval graph covers start/end events, user tasks, exclusive gateways, plus AuraBoot's extended rule task, record-update task, and notification task.
  • Runtime — submitting a request makes Smart Engine instantiate the process and drive task assignment and routing by the graph.
  • Rule engine — Drools rules decide who approves, and run a pre-flight validation before submission.
  • SLA — approval tasks carry a deadline, warning, and escalation policy.

After this page you'll know what each piece looks like in config, and how to run it locally.

Demo scenario: leave approval

A leave request goes from draft to archive: validate, route to an approver by duration, get human approval, write the status back, notify the applicant. workflow-demo models this as a process definition wd_leave_approval, bound to the model wd_leave_request, triggered by the command wd:submit_leave_request.

draft
  └─ wd:submit_leave_request
       ├─ pre-flight rule wd_leave_validation (balance / sick-leave attachment)
       ├─ start process wd_leave_approval (postActions.start_process)
       └─ state transition draft|rejected → submitted
            └─ engine runs the graph: rule route → gateway → approval task (with SLA)
                 → result gateway → write status → notify → end

The full graph

The wd_leave_approval graph (the designer's designerJson) uses the nodes below. The BPMN Designer palette supports 12 node types in total; this example uses 7 of them, including 3 AuraBoot extension nodes.

NodeType (type)Purpose
Start (start_1)startEventProcess entry
Routing Rule (svc_rule_route)rule-taskCalls Drools rule wd_leave_routing, produces approverRole
Approver Dispatch (gw_approver)exclusiveGatewayPicks manager / hr branch by approverRole
Manager Approve (task_manager_approve)userTaskAssigned to role wd_manager, carries SLA wd_manager_approve_sla
HR Approve (task_hr_approve)userTaskAssigned to role wd_hr, carries SLA wd_hr_approve_sla
Decision (gw_result)exclusiveGatewayPicks approved / rejected branch by taskResult
Set Status (svc_set_approved / svc_set_rejected)record-update-taskWrites the wd_req_status field
Notify Applicant (svc_notify_approved / svc_notify_rejected)notification-taskEmits event wd_request_approved / wd_request_rejected
Approved / Rejected (end_*)endEventProcess exit

📷 Screenshot slot — BPMN Designer with wd_leave_approval open, full-node canvas (host-first capture pending).

Designer: how nodes are configured

The graph is stored as designer JSON (nodes + edges + process-level aura policy) and compiled to BPMN 2.0 on publish. Here is how a few key nodes appear in designerJson.nodes.

Rule task — references a rule by ruleCode; factsVars declares which process variables become rule facts:

{
  "id": "svc_rule_route",
  "type": "rule-task",
  "data": {
    "label:en": "Routing Rule",
    "ruleCode": "wd_leave_routing",
    "factsVars": "days,type"
  }
}

User taskconfig.assignee declares the assignment strategy (by role here), slaKey links the task to an SLA, and taskActions defines the actions an approver can take:

{
  "id": "task_manager_approve",
  "type": "userTask",
  "data": {
    "label:en": "Manager Approve",
    "formPageKey": "wd_leave_request_detail",
    "slaKey": "wd_manager_approve_sla",
    "config": { "assignee": { "type": "role", "roleIds": ["wd_manager"] } },
    "taskActions": [
      { "key": "approve", "type": "complete", "resultVariable": "taskResult", "resultValue": "approved" },
      { "key": "reject", "type": "complete", "resultVariable": "taskResult", "resultValue": "rejected", "requireComment": true }
    ]
  }
}

Record-update task / notification task — AuraBoot extension nodes on top of standard BPMN, so the flow can write record fields and emit business events without hand-written serviceTask glue:

{
  "id": "svc_set_approved",
  "type": "record-update-task",
  "data": { "modelCode": "wd_leave_request", "recordIdVar": "recordId", "fieldName": "wd_req_status", "fieldValue": "approved" }
}

Edges carry condition expressions to branch. The approver-dispatch gateway's two outgoing edges are ${approverRole == 'manager'} and ${approverRole == 'hr'}; the result gateway uses ${taskResult == 'approved'} / ${taskResult == 'rejected'}.

Runtime: Smart Engine

AuraBoot embeds Smart Engine (an AuraBoot-maintained fork of the BPMN engine) as the process runtime. After deploy, instances are triggered by the Command Pipeline — the postActions of wd:submit_leave_request start the process once the state transition succeeds, and write the instance id back to the record field wd_req_process_instance:

{
  "code": "wd:submit_leave_request",
  "type": "state_transition",
  "modelCode": "wd_leave_request",
  "stateField": "wd_req_status",
  "fromStates": ["draft", "rejected"],
  "toState": "submitted",
  "postActions": [
    {
      "type": "start_process",
      "processKey": "wd_leave_approval",
      "businessKey": "${recordId}",
      "variables": { "days": "${payload.wd_req_days}", "type": "${payload.wd_req_type}", "recordId": "${recordId}", "applicantUserId": "${payload.wd_req_applicant}" },
      "storeInstanceIdIn": "wd_req_process_instance"
    }
  ]
}

Once started, the engine advances the graph: evaluate rule task → gateway picks branch → create the approval task and assign by role → wait for human completion → result gateway → write status → notify → end. The Command Pipeline remains the single source of truth for data changes; Smart Engine only orchestrates who does the next step, and when.

Process definitions and runtime are exposed under /api/bpm/*. Key endpoints:

OperationEndpoint
Validate process JSON (before deploy)POST /api/bpm/process-definitions/validate
Deploy processPOST /api/bpm/process-definitions/{pid}/deploy
Suspend / resume instancePOST /api/bpm/process-definitions/{pid}/suspend …/resume
Todo / completed tasksGET /api/bpm/tasks/todo …/completed
Approve / rejectPOST /api/bpm/tasks/{taskId}/approve …/reject

Cancellation runs through the wd:cancel_leave_request command, whose postActions use withdraw_process to close the running approval task.

Wiring in the rule engine

workflow-demo uses two Drools rules to show the two places a rule engine plugs in.

Pre-flight (before the command)wd_leave_validation (ruleType: VALIDATION) runs before wd:submit_leave_request starts the process, blocking annual leave with insufficient balance and long sick leave without an attachment:

{
  "ruleCode": "wd_leave_validation",
  "ruleType": "VALIDATION",
  "outputSchema": { "type": "object", "properties": { "valid": { "type": "boolean" }, "reason": { "type": "string" } } },
  "ruleContentFile": "rules/wd_leave_validation.drl"
}

In-process routing (rule-task)wd_leave_routing (ruleType: CONDITION) is called by the svc_rule_route node, producing approverRole from the number of days for the downstream exclusive gateway:

rule "route_short_to_manager"
    when
        $req: Map( ((Number) this["days"]).doubleValue() < 3.0 )
    then
        ((Map) $req.get("_ruleResult")).put("approverRole", "manager");
end

rule "route_long_to_hr"
    when
        $req: Map( ((Number) this["days"]).doubleValue() >= 3.0 )
    then
        ((Map) $req.get("_ruleResult")).put("approverRole", "hr");
end

Rules are not compiled into the BPMN — the flow only stores a ruleCode reference, and the engine calls back to the rule service when it reaches the rule task. A rule can be tried independently via POST /api/bpm/rules/{pid}/evaluate, which makes it easy to debug decoupled from the flow.

Wiring in SLA

Each approval task carries an SLA (config/sla.json) to add time accountability: deadline, warning, overdue escalation, suspend policy.

{
  "slaKey": "wd_manager_approve_sla",
  "name:en": "Manager Approval SLA",
  "targetType": "NODE",
  "targetKey": "task_manager_approve",
  "processKey": "wd_leave_approval",
  "deadlineMode": "FIXED",
  "deadlineValue": "PT30S",
  "warningRules": [ { "beforeSeconds": 10, "eventType": "sla_warning", "notifyTargets": ["assignee"] } ],
  "suspendPolicy": "pause",
  "escalationTargetType": "role_parent",
  "escalationTargetValue": "wd_manager",
  "enabled": true
}

What the fields mean:

  • targetType: NODE + targetKey — the SLA binds to a node in the flow (also supports PROCESS / TASK).
  • deadlineMode: FIXED + deadlineValue — an ISO-8601 duration sets the deadline. The demo uses PT30S (30 seconds) so E2E can observe escalation quickly; production should use a real value like PT24H.
  • warningRules — emit a warning event and notify the listed targets N seconds before the deadline.
  • suspendPolicy: pause — pause the timer while the process is suspended and resume it afterwards, so suspended time is not counted as overdue.
  • escalationTargetType / escalationTargetValue — who the task escalates to after the deadline.

A task's SLA state is visible in the Task Center; the running SLA record updates as the task is claimed, completed, suspended, or resumed.

Run it yourself

workflow-demo is an OSS plugin and is imported by default with the open-source demo environment. To import and seed it manually:

# 1) Import the plugin (config-only + backend jar; build the backend jar first on first run)
aura plugin-import plugins/workflow-demo --conflict-strategy overwrite --yes

# 2) Seed demo data through product APIs (leave balances + requests + task history)
node scripts/seed-workflow-demo.mjs

For the import mechanics (plugin.json / resourceDirs / backend jar) see Config-only Plugins and Plugin Development.

Once running, enter from the Leave Demo sidebar group:

  • My Requests (/p/wd_leave_request) — click "Submit" on a draft row, confirm, and that fires wd:submit_leave_request and starts the process.
  • Leave Balances (/p/wd_leave_balance) — the balance data used by pre-flight validation.
  • Task Center — find the approval task for the matching businessKey, click "Approve / Reject" to advance the flow, and watch the SLA state.

📷 Screenshot slot — Task Center approving a wd_leave_approval task + SLA state (host-first capture pending).

Verification checklist

Running this flow end to end, you should be able to verify each of:

  1. Submitting annual leave that exceeds the remaining balance is blocked by wd_leave_validation (the process does not start).
  2. Submitting days < 3 routes to the manager; days >= 3 routes to HR (rule + gateway take effect).
  3. The approval task appears in the Task Center, assigned by role.
  4. Not acting before the deadline triggers an SLA warning / escalation.
  5. "Approve" writes wd_req_status back to approved and the applicant is notified; "Reject" writes rejected.
  6. The audit trail records process_start + rule / gateway / userTask activity events + the approve operation.

Next steps