I'm working on a proof-of-concept that needs to provide runtime support for the execution of business processes.
Right now, I'm happy to use the Flowable Modeler to model business processes and to create User tasks and process instances, however, I'd also like to use Flowable's REST API to interact with process instances and User tasks.
Flowable Modeler
The easiest way to get started with Flowable is to use the flowable/all-in-one Docker image:
docker run --name flowable -p 8080:8080 flowable/all-in-one
or
docker start --interactive flowable
Navigate to http://localhost:8080/flowable-modeler
and sign in using the default user id: admin and password: test
You will then be redirected to the Processes tab in the Flowable Modeler's dashboard:
To begin modelling a business process (using BPMN) click the Create Process button:
Enter a Model name
, a Model key
and a Description
then click the Create new model button:
The 'process design interface' (Flowable's BPMN editor) includes a side menu with a palette of BPMN 2.0 elements and a properties panel at the bottom of the page. Each new process begins with a Start event (the small circle).
You can drag and drop elements from the side menu, or you can use the 'quick menu' of a selected element. Click on the Start event element and its quick menu will appear.
We’re going to add a User task, so click the icon representing a user:
This will add a box linked by an arrow to the Start event. Double-click on the box to give the task the name 'Fill in a Leave Application Form' and then click outside the box to save the change:
Click on the box again to display its quick menu and select the Stop event icon (the circle with a thick border):
Our business process model now consists of a Start event, a User task and an End event:
Assignments
In order for Flowable to successfully execute our business process it needs to know which users can complete the User task. Select the 'Fill in a Leave Application Form' User task and then click its Assignments
property:
You can assign the task to an individual or a group:
Check the 'Allow process initiator to complete task' box and then click the Save button.
Form Reference
To associate a form with a User task, select the 'Fill in a Leave Application Form' User task and then click its Form reference
property:
We don't have any forms just yet:
Click the New form button:
Enter a Form name
, a Form key
and a Description
then click the Create form button:
The Form designer includes a side menu with a palette of form components that you can drag and drop onto the design canvas:
App Definitions
Now that we have modelled our business process we need to make it available for people to use. Navigate to the Apps tab in the Flowable Modeler's dashboard and click the Create App button:
Enter an App definition name
, an App definition key
and a Description
then click the Create new app definition button:
I changed the Icon, used the Edit included models button to add the 'Leave Application Process' to the 'HR App' and then clicked the Save icon:
Click the 'HR App' card:
Note: You can export the App definition as a zip file or as a deployable bar file.
Click the Publish button:
Click the Publish app definition button.
Now we'll use Flowable's REST API to check and see if our app definition has been deployed:
curl -i 'http://admin:test@localhost:8080/flowable-task/process-api/repository/deployments'
You should see output like:
{
"data": [
{
"id": "c56b72eb-06f8-11e9-a85e-0242ac110002",
"name": "hr-app.zip",
"deploymentTime": "2018-12-23T21:21:54.532Z",
"category": null,
"parentDeploymentId": "c55ec8b6-06f8-11e9-a85e-0242ac110002",
"url": "http://localhost:8080/flowable-task/process-api/repository/deployments/c56b72eb-06f8-11e9-a85e-0242ac110002",
"tenantId": ""
}
],
"total": 1,
"start": 0,
"sort": "id",
"order": "asc",
"size": 1
}
Let's check and see if our process definition has been deployed too:
curl -i 'http://admin:test@localhost:8080/flowable-task/process-api/repository/process-definitions'
You should see output like:
{
"data": [
{
"id": "leave-application-process:1:c5ae6f5e-06f8-11e9-a85e-0242ac110002",
"url": "http://localhost:8080/flowable-task/process-api/repository/process-definitions/leave-application-process:1:c5ae6f5e-06f8-11e9-a85e-0242ac110002",
"key": "leave-application-process",
"version": 1,
"name": "Leave Application Process",
"description": "An employee wants to take some time off.",
"tenantId": "",
"deploymentId": "c56b72eb-06f8-11e9-a85e-0242ac110002",
"deploymentUrl": "http://localhost:8080/flowable-task/process-api/repository/deployments/c56b72eb-06f8-11e9-a85e-0242ac110002",
"resource": "http://localhost:8080/flowable-task/process-api/repository/deployments/c56b72eb-06f8-11e9-a85e-0242ac110002/resources/leave-application-process.bpmn",
"diagramResource": "http://localhost:8080/flowable-task/process-api/repository/deployments/c56b72eb-06f8-11e9-a85e-0242ac110002/resources/leave-application-process.leave-application-process.png",
"category": "http://www.flowable.org/processdef",
"graphicalNotationDefined": true,
"suspended": false,
"startFormDefined": false
}
],
"total": 1,
"start": 0,
"sort": "name",
"order": "asc",
"size": 1
}
Flowable Task
Navigate to http://localhost:8080/flowable-task
Click the 'HR App' card and navigate to the Processes tab:
Click the Start a process button:
Then click the Start process button:
Now we'll use Flowable's REST API to obtain information about our process instances:
curl -i 'http://admin:test@localhost:8080/flowable-task/process-api/runtime/process-instances'
You should see output like:
{
"data": [
{
"id": "02d460bb-070e-11e9-a85e-0242ac110002",
"url": "http://localhost:8080/flowable-task/process-api/runtime/process-instances/02d460bb-070e-11e9-a85e-0242ac110002",
"name": "Leave Application Process - December 24th 2018",
"businessKey": null,
"suspended": false,
"ended": false,
"processDefinitionId": "leave-application-process:1:c5ae6f5e-06f8-11e9-a85e-0242ac110002",
"processDefinitionUrl": "http://localhost:8080/flowable-task/process-api/repository/process-definitions/leave-application-process:1:c5ae6f5e-06f8-11e9-a85e-0242ac110002",
"activityId": null,
"startedBy": "admin",
"started": "2018-12-23T23:53:56.992Z",
"variables": [],
"callbackId": null,
"callbackType": null,
"tenantId": "",
"completed": false
}
],
"total": 1,
"start": 0,
"sort": "id",
"order": "asc",
"size": 1
}
Let's check and see if we have any tasks to complete:
curl -i 'http://admin:test@localhost:8080/flowable-task/process-api/runtime/tasks'
You should see output like:
{
"data": [
{
"id": "1fae489a-070f-11e9-a85e-0242ac110002",
"url": "http://localhost:8080/flowable-task/process-api/runtime/tasks/1fae489a-070f-11e9-a85e-0242ac110002",
"owner": null,
"assignee": "admin",
"delegationState": null,
"name": "Fill in a Leave Application Form",
"description": null,
"createTime": "2018-12-24T00:01:54.893Z",
"dueDate": null,
"priority": 50,
"suspended": false,
"taskDefinitionKey": "sid-3BA1F4D1-500F-4766-89BF-519166929F2D",
"scopeDefinitionId": null,
"scopeId": null,
"scopeType": null,
"tenantId": "",
"category": null,
"formKey": "leave-application-form",
"parentTaskId": null,
"parentTaskUrl": null,
"executionId": "1fadfa77-070f-11e9-a85e-0242ac110002",
"executionUrl": "http://localhost:8080/flowable-task/process-api/runtime/executions/1fadfa77-070f-11e9-a85e-0242ac110002",
"processInstanceId": "1fadfa74-070f-11e9-a85e-0242ac110002",
"processInstanceUrl": "http://localhost:8080/flowable-task/process-api/runtime/process-instances/1fadfa74-070f-11e9-a85e-0242ac110002",
"processDefinitionId": "leave-application-process:1:c5ae6f5e-06f8-11e9-a85e-0242ac110002",
"processDefinitionUrl": "http://localhost:8080/flowable-task/process-api/repository/process-definitions/leave-application-process:1:c5ae6f5e-06f8-11e9-a85e-0242ac110002",
"variables": []
}
],
"total": 1,
"start": 0,
"sort": "id",
"order": "asc",
"size": 1
}
formKey
contains the name of the form ('leave-application-form') associated with the User task.
We can check the form repository for the 'Leave Application Form':
curl -i 'http://admin:test@localhost:8080/flowable-task/form-api/form-repository/form-definitions'
You should see output like:
{
"data": [
{
"id": "c5bdb1a1-06f8-11e9-a85e-0242ac110002",
"url": "http://localhost:8080/flowable-task/form-api/form-repository/form-definitions/c5bdb1a1-06f8-11e9-a85e-0242ac110002",
"category": null,
"name": "Leave Application Form",
"key": "leave-application-form",
"description": null,
"version": 1,
"resourceName": "form-leave-application-form.form",
"deploymentId": "c5b0b94f-06f8-11e9-a85e-0242ac110002",
"tenantId": ""
}
],
"total": 1,
"start": 0,
"sort": "name",
"order": "asc",
"size": 1
}
We can use the id
to obtain a JSON representation of the form model:
curl -i 'http://admin:test@localhost:8080/flowable-task/form-api/form-repository/form-definitions/c5bdb1a1-06f8-11e9-a85e-0242ac110002/model'
You should see output like:
{
"id": "c5bdb1a1-06f8-11e9-a85e-0242ac110002",
"name": "Leave Application Form",
"key": "leave-application-form",
"version": 1,
"url": "http://localhost:8080/flowable-task/form-api/form/model",
"fields": [
{
"fieldType": "FormField",
"id": "givenName",
"name": "Given Name",
"type": "text",
"value": null,
"required": true,
"readOnly": false,
"overrideId": true,
"placeholder": "",
"layout": null
},
{
"fieldType": "FormField",
"id": "familyName",
"name": "Family Name",
"type": "text",
"value": null,
"required": true,
"readOnly": false,
"overrideId": true,
"placeholder": null,
"layout": null
},
{
"fieldType": "FormField",
"id": "employeeNumber",
"name": "Employee Number",
"type": "integer",
"value": null,
"required": true,
"readOnly": false,
"overrideId": true,
"placeholder": null,
"layout": null
},
{
"fieldType": "FormField",
"id": "fromDate",
"name": "From Date",
"type": "date",
"value": null,
"required": true,
"readOnly": false,
"overrideId": true,
"placeholder": null,
"layout": null
},
{
"fieldType": "FormField",
"id": "toDate",
"name": "To Date",
"type": "date",
"value": null,
"required": true,
"readOnly": false,
"overrideId": true,
"placeholder": null,
"layout": null
}
],
"outcomes": []
}
Now navigate to the Tasks tab to see how Flowable's Form engine renders our Leave Application form:
We can fill in the form:
Or use Flowable's REST API to update the form's variables and to complete the User task:
curl -H "Content-Type: application/json"
-X POST http://admin:test@localhost:8080/flowable-task/process-api/runtime/tasks/1fae489a-070f-11e9-a85e-0242ac110002
-d "@data-1.json"
data-1.json:
{
"action" : "complete",
"variables" : [
{
"id": "givenName",
"name": "Given Name",
"type": "string",
"value": "Rob"
},
{
"id": "familyName",
"name": "Family Name",
"type": "string",
"value": "Ferguson"
},
{
"id": "employeeNumber",
"name": "Employee Number",
"type": "integer",
"value": 123456
},
{
"id": "fromDate",
"name": "From Date",
"type": "date",
"value": "2018-12-21T00:00:00+00:00"
},
{
"id": "toDate",
"name": "To Date",
"type": "date",
"value": "2019-01-07T00:00:00+00:00"
}
]
}
You should see output like:
Status: 200 OK
Despite returning OK the call doesn't appear to save the User task's variables:
So I raised the following Flowable issue:
- Flowable Engine: POST /runtime/tasks/{taskId}
I also tried, POST /form/form-data
curl -H "Content-Type: application/json"
-X POST http://admin:test@localhost:8080/flowable-task/process-api/form/form-data
-d "@data-2.json"
data-2.json:
{
"taskId" : "1fae489a-070f-11e9-a85e-0242ac110002",
"properties" : [
{
"id": "givenName",
"name": "Given Name",
"type": "string",
"value": "Rob"
},
{
"id": "familyName",
"name": "Family Name",
"type": "string",
"value": "Ferguson"
},
{
"id": "employeeNumber",
"name": "Employee Number",
"type": "integer",
"value": 123456
},
{
"id": "fromDate",
"name": "From Date",
"type": "date",
"value": "2018-12-21T00:00:00+00:00"
},
{
"id": "toDate",
"name": "To Date",
"type": "date",
"value": "2019-01-07T00:00:00+00:00"
}
]
}
You should see output like:
Status: 204 No Content
I'm not sure why its returning 204 No Content
so I raised the following Flowable issue:
- Flowable Engine: POST /form/form-data
However it does appear to save the User task's variables (and complete the User task):
Flowable Issues
I raised the following Flowable issues:
- Flowable Engine: POST /runtime/tasks/{taskId}
- Flowable Engine: POST /form/form-data
- Flowable Engine: JSON body parameters
What's Next
In the next post, we'll use Angular, Angular Material and Flowable's REST API to create a bespoke Task List component:
Source Code:
- GitHub: Serendipity
References:
- Paul Holmes-Higgin's blog: Instant Gratification with Flowable 6
- Flowable docs: REST API
- GitHub: Flowable REST API Documentation