Executing a BPMN Process

Let’s assume we have a basic BPMN process defined through the modeler as below having name as first-bpmn.

The workflow

It uses a script task and a user task. Script node is configured to execute a simple inline javascript code as below. The code combines firstName and lastName process variables and sets fullName as new process variable. Finally it passes a new object as a message to user task node.

let fullName = pv('firstName') + ' ' + pv('lastName');
setPV('fullName', fullName);
sendMsg({name: fullName})

The user task has a task category configured as Basic Task.

Terminology

  • Workflow Instance : Every BPMN process relates to one WorkflowInstance record.
  • Process Instance : A Workflow Instance has one or more associated ProcessInstance records. When a BPMN diagram contains sub-flows, each of those sub-flow is represented by separate ProcessInstance record belonging to same WorkflowInstance as parent.
  • Process Variables : Business data associated with process are maintained as process variables. This is a free form javascript object and can contain any arbitrary key/value pair. Various nodes in the BPMN process can enrich, alter or remove process variables. Process variables are cumulative as process execution progresses.
  • Message : In addition to modifying process variables, a node can pass a message object to next node. While process variables maintain the overall business data status, messages are meant for passing node execution status to next node.

Trigger the process

A BPMN process can be triggered in following ways

To trigger the process manually, create a new workflow instance through following API and passing firstName and lastName as two process variables.

Verb Url Payload
POST /api/WorkflowInstances see below
{
	"workflowDefinitionName": "first-bpmn",
	"processVariables": {
    "firstName": "Alex",
    "lastName": "Yankovicz"
  }
}

Following new workflow instance data is returned as response and BPMN process starts execution.

{
    "workflowDefinitionName": "first-bpmn",
    "workflowDefinitionId": "16799c1d-a1ff-4904-bbfa-ae9d84ad5164",
    "processVariables": {
        "firstName": "Alex",
        "lastName": "Yankovicz"
    },
    "id": "5e56366aee83a24e498f3499"
}

Actual identifier values may defer

Notice that the instance locks on to the current active version of BPMN process definition by name first-bpmn.

Check the status

Based on the workflow instance id returned above, make following API call to get the current process details,

Verb Url Payload
GET /api/WorkflowInstances/workflow-instance-id/processes none

e.g. http://localhost:3000/api/WorkflowInstances/5e56366aee83a24e498f3499/processes

[
    {
        "processDefinitionName": "first-bpmn",
        "processDefinitionBpmnId": "Process_1",
        "_processTokens": {
            "85309b81-30fa-439b-b370-6d6c784eb7cb": {
                "name": "Start",
                "startTime": "2020-02-26T09:12:10.285Z",
                "bpmnId": "StartEvent_1",
                "id": "85309b81-30fa-439b-b370-6d6c784eb7cb",
                "status": "complete",
                "endTime": "2020-02-26T09:12:10.290Z"
            },
            "621acf7b-0621-4d0a-b7a5-f61bc58e8896": {
                "name": "Script",
                "bpmnId": "Task_1e80er7",
                "status": "complete",
            },
            "886044b5-07ed-4201-8648-a72e2379a4bb": {
                "name": "UserTask",
                "bpmnId": "Task_0qknezx",
                "status": "pending",
                "message": {
                    "name": "Alex Yankovicz"
                },
                "isUserTask": true,
                "taskId": "5e56366aee83a24e498f349d"
            }
        },
        "_processVariables": {
            "firstName": "Alex",
            "lastName": "Yankovicz",
            "_workflowInstanceId": "5e56366aee83a24e498f3499",
            "fullName": "Alex Yankovicz",
        },
        ...
        ...
        "_status": "running",
        "id": "5e56366aee83a24e498f349a",
        "workflowInstanceId": "5e56366aee83a24e498f3499"
    }
]

The API returns one or more process instances associated with workflow instance. The process instance contains details about each of the node exeution and it’s status. In above case, Start and Script task are completed and UserTask is in pending status.

The User Task node creates a Task record and suspends the flow execution.

Fetching user tasks

Verb Url Description
GET /api/ProcessInstances/process-instance-id/tasks Fetches all tasks associated with given process instance
GET /api/Tasks Fetches all tasks

e.g. http://localhost:3000/api/ProcessInstances/5e56366aee83a24e498f349a/tasks

The response contains following task data

[
    {
        "name": "UserTask",
        "status": "pending",
        "processTokenId": "886044b5-07ed-4201-8648-a72e2379a4bb",
        "formVariables": {
            "firstName": "Alex",
            "lastName": "Yankovicz",
            "_workflowInstanceId": "5e56366aee83a24e498f3499",
            "fullName": "Alex Yankovicz",
        },
        "message": {
            "name": "Alex Yankovicz"
        },
        "id": "5e56366aee83a24e498f349d",
        "processInstanceId": "5e56366aee83a24e498f349a",
        "workflowInstanceId": "5e56366aee83a24e498f3499"
    }
]

Notice that current process variables are copied over as formVariables. The task identifier is available under id property. The message passed from script node is available in user task token as well as Task record.

Complete the task

To complete a user task you must invoke following API

Verb Url Description
PUT /api/Tasks/task-id/complete completes the given task
{
  "pv": {
    "age": 28
  },
  "msg": "All Done"
}

API returns the task record having status as completed.

Querying the latest process status reports that BPMN process has completed.

    {
        "processDefinitionName": "first-bpmn",
        "processDefinitionBpmnId": "Process_1",
        "_processTokens": {
            "85309b81-30fa-439b-b370-6d6c784eb7cb": {
                "name": "Start",
                "bpmnId": "StartEvent_1",
                "status": "complete",
            },
            "621acf7b-0621-4d0a-b7a5-f61bc58e8896": {
                "name": "Script",
                "bpmnId": "Task_1e80er7",
                "status": "complete",
            },
            "886044b5-07ed-4201-8648-a72e2379a4bb": {
                "name": "UserTask",
                "bpmnId": "Task_0qknezx",
                "status": "complete",
                "message": {
                    "name": "Alex Yankovicz"
                },
                "isUserTask": true,
                "taskId": "5e56366aee83a24e498f349d",
            },
            "672e687f-3c94-4e59-ba18-1eb5c99ff028": {
                "name": "End",
                "bpmnId": "EndEvent_07dglq5",
                "status": "complete",
                "message": "All Done",
            }
        },
        "_processVariables": {
            "firstName": "Alex",
            "lastName": "Yankovicz",
            "_workflowInstanceId": "5e56366aee83a24e498f3499",
            "fullName": "Alex Yankovicz",
            "age": 28
        },
        ...
        "id": "5e56366aee83a24e498f349a",
        "workflowInstanceId": "5e56366aee83a24e498f3499"
    }
  • _processTokens contains 4 tokens corresponding to Start, Script, UserTask and End nodes. All 4 tokens are completed.
  • pv values sent in complete API are applied to main process variables.
  • msg value is passed on to next node (End node in this case).