Use GEARS API - XLRIT/gears GitHub Wiki
1. Table of content
2. Introduction
The GEARS runtime uses GraphQL as its API. This document assumes basic knowledge on using GraphQL, mainly queries (getting data) and mutations (changing data).
Also note that this document does not explain how to call the API from say JavaScript, Java, or any existing programming language. You'll have to figure that out on your own. But don't worry. the internet is filled with a ton of examples for different languages.
And the last thing to say before we start is that it is common to use query variables. We'll only show how this works in the first example. However, to make this document easy to read, we will not use this approach in the remainder of this document.
3. Prerequisites
- You have at least one case up and running as described in Home. We'll use the leave_of_absence demo case as an example.
- You have installed the GraphQL Playground or an equivalent GraphQL development environment.
- In the current version of the GEARS runtime (0.88) it is required to add the following to the
application.yml
file (if not the GraphQL Playground will not be able to communicate with the GraphQL API of the runtime, due to CORS):
graphql:
servlet:
cors:
allowed-origins: '*'
allowed-methods: '*'
allowed-headers: '*'
allow-credentials: false
4. How to use the GEARS API
4.1. Get GEARS GraphQL docs
For the most part GraphQL API's are self documented. The easiest way to get this documentation is to enter the GraphQL URL ENDPOINT when you start the GraphQL playground (in short called playground from now on). The URL ENDPOINT of the GEARS API is:
When you have entered this in the playground you should see vertical tabs (DOCS and SCHEMA) on the right of the screen, which you can expand and browse:
Although the documentation helps, it is for now only a limited reference. So don't spent too much time on reading this right now, but quickly go to the next paragraphs.
4.2. Login
The following mutation will log a user in based on username
and password
:
mutation { login(username: "demo", password: "demo") }
When using query variables this query would look like this:
mutation LoginMutation($username: String!, $password: String!) {
login(username: $username, password: $password)
}
In the playground you would have provide the values for $username
and $password
by entering them as JSON key value pairs under QUERY VARIABLES. In this example you would enter this text:
{ "username": "demo", "password": "demo"}
If you run this query in the playground, the result looks a bit like this:
This means you now have received a "Bearer token" that can be used to identify a logged in user. In this example the Bearer token is a long string starting with eyJ0e...
and ends with _taD4M
You can put this Bearer token in the HTTP header so the GEARS GraphQL API knows who the logged in user is. Just click on HTTP HEADERS and enter the token as in the following example:
{ "Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkZW1vIiwiZm9vIjoiYmFyIiwiaXNzIjoiWExSSVQiLCJpYXQiOjE2MTI1MjcwMzd9.OIb7-HLjiPq5lAOm7q2ua-P-0m8rY3J95VqlhIf3gSo"}
In the next paragraphs I will assume you have done so.
Note that: the demo
user is authorized for everything. There are also users that can only start processes and perform tasks for certain roles.
user | role |
---|---|
employee1 | EMPLOYEE |
employee2 | EMPLOYEE |
manager1 | MANAGER |
manager2 | MANAGER |
customer1 | CUSTOMER |
customer2 | CUSTOMER |
aanvrager1 | AANVRAGER |
beoordelaar1 | BEOORDELAAR |
In the process diagram (see example below) you see the role in the task name. For instance: in the task Task 1 From EMPLOYEE: ... the role is EMPLOYEE. As this is the first task of a process, only users with that role are authorized to list and start this his/hers processes.
4.3. Get list of startable processes
Getting a list of startable processes is an example of a GraphQL query (get data). Below is an example of this query which I have named GetProcessDefinitions
. Once again, you can name them as you like. Besides this, one of the benefits of GraphQL is that you can also choose which fields you would like to retrieve, so if you only need key
, name
and description
, than you only need to provide these attribute names.
query GetProcessDefinitions {
processDefinitions {
id
key
name
description
hasStartForm
}
}
You should get a list of processes this user can start. For instance like this:
{
"data": {
"processDefinitions": [
{
"id": "loa.absence.request:1:01FXAJBTR245JSATJNEJMTZDY0",
"key": "loa.absence.request",
"name": "Request absence",
"description": "Request a leave of absence",
"hasStartForm": false
}
]
}
}
Of course you should only get a list of process definitions that can be started by the logged in user. For this example case you can try this by first logging in as manager1, then put the bearer token in the HTTP HEADERS as described above, and then try to run the GetProcessDefinitions
query again. You will see that you will not get the process called "Request absence"
.
4.4. Start a process
The previous query resulted in a value called "key"
with a value of "loa.absence.request"
. The following query can be used to start that process.
mutation { startProcessByKey(key:"loa.absence.request") { id, tasks { id } } }
Note that this call also explicitly asks for extra data, such as the id
of the started process (called a "process instance") all tasks
that are started as a result of starting this process and for each task, its id
. The result would look like this:
{
"data": {
"startProcessByKey": {
"id": "01FXAKFKQPAXHVBV71FCMTK7KB",
"tasks": [
{
"id": "01FXAKFKQQNX56DGB8H9T4E17K"
}
]
}
}
}
You have now started a process. The "id"
of the first tasks (in this example just one). This task "id"
can be used to claim and open this task, which we will do in the next paragraph.
4.5. List of tasks
Consistent with the GEARS Frontend you can retrieve a list of two types of tasks:
- Assigned tasks: tasks that are already assigned to the logged in user.
- Group tasks: tasks that the logged in user is authorized to start (claim and open).
Below are the matching queries to get these lists:
query {
assignedTasks {
id
name
subject
assignee
allowedRoles
processDefinition { name }
}
}
and
query {
groupTasks {
id
name
subject
assignee
allowedRoles
processDefinition { name }
}
}
4.6. Claim and open a task.
The process flow framework that the GEARS runtime uses has a 2 phase approach to actually start a task:
- Claim a task: which is basically assigning a specific user to a task. In this case the logged in user. If you claim a task, the task moves from Group tasks to the Assigned tasks of the user who has claimed it.
- Open a task: which is getting the info of a task to inform the user how to perfom the task.
This is an example of claiming a task:
mutation { claimTask(id: "01FXAJS4EVZ5D54M6AE52SD4TB") }
And right after that a task can be "opened" (read) with the same id
like this:
query {
task(id:"01FXAJS4EVZ5D54M6AE52SD4TB") {
name
documentation
form
}
}
Below is an example of the second task in the leave of absence case.:
{
"data": {
"task": {
"name": "Task 2 for Manager",
"documentation": {
"nr": 2,
"for": "Manager",
"structure": [
{
"kind": "input",
"name": "decision",
"parent": "LEAVE_REQUEST"
},
{
"kind": "input",
"name": "reason",
"parent": "LEAVE_REQUEST"
}
]
},
"subject": "(none)",
"form": {
"fields": [
{
"path": "decision",
"name": "decision",
"baseName": "decision",
"parentName": "LEAVE_REQUEST",
"type": "TEXT",
"label": "Decision",
"optional": false,
"labeled": false,
"isLabeled": false
},
{
"path": "reason",
"name": "reason",
"baseName": "reason",
"parentName": "LEAVE_REQUEST",
"type": "TEXT",
"label": "Reason",
"optional": false,
"labeled": false,
"isLabeled": false
}
],
"values": {
"decision": "approved",
"reason": null,
"__basedOn": {
"__kind": "tuple",
"Requestor": "Danny Demo",
"Type": "sickness",
"Start": "2022-03-04",
"End": "2022-04-01"
}
},
"aux": {
"decision": {
"choices": [
{
"value": "approved",
"label": "approved"
},
{
"value": "rejected",
"label": "rejected"
}
]
},
"reason": {}
}
}
}
}
}
Most don't need explanation, but these may:
Field | Explanation |
---|---|
documentation |
this is a but of JSON that explains for which type of user (role) this task is and what this user has to enter (input ). |
form |
this defines the form the user would normally be presented with. It contains the fields, from which entity they are part of (e.g. LEAVE_REQUEST ), their labels on the screen and their types (e.g. TEXT or DATE , etc.). |
values |
this contains either default values for input fields but also a __basedOn which contains the read only information the user needs to be able to enter the input fields. |
aux |
this defines which choices the users can choose from for each field (only filled if needed). |
4.7. Submit a task and handle follow up tasks
Sumitting a task is done with the submitTask
mutation. This mutation requires 2 parameters:
id
: which is the task id if the task you want to submit. For instance the same id you used to open the task.values
: this coincides with thevalues
key which you got when opening a task (as described previously) but of course now you can fill in the values with actual values.
Below is an example of submitting a leave of absence request with a type
set to holiday
and a start
of the 13th of February 2021 and a end
of the 25th of February 2021.
mutation { submitTask( id: "01FXAPMNWWM6WJ7X1E61T3N6VE",
values: { decision: "rejected",
reason: "Too many Corona cases"
}
) { __typename
... on ProcessInstance { id, assignedTasks { id } }
... on ProcessInstanceEnded { id }
... on InputErrors { errors { path, name, type, label, value, status, message } }
}
}
A possible response could look like this:
{
"data": {
"submitTask": {
"__typename": "ProcessInstanceEnded",
"id": "01FXJZKTX718J04G9PGZNPN603"
}
}
}
As you may already gave guessed, the __typename
and what follows is a typical GraphQL concept of a reponse that may vary depending on the situation. Apparently there are 3 types of results, which suggest 3 types of situations.
Response type / situation | Explanation |
---|---|
ProcessInstance |
Process has not yet ended and may even produce 0 or more assignedTasks as follow up task for this user. |
ProcessInstanceEnded |
The process has ended. |
InputErrors |
The task could not be submitted succesfully due to errors . Each error contains information about the field that has been filled incorrectly as well as a message saying what the error was (e.g. Field "Start" should be filled with a data value. ). |
Good to know:
- the
values
key looks almost identical to the result you get back when opening a task as described in the previous section. The only difference is that in that result the keys are surrounded with double quotes ("..."
) while when submitting a task the keys do not have double quotes around them. - Interestingly enough, you could use the GEARS Frontend to fill in the task by hand and than press the Save button instead of the Submit button. If you would then open the same task but with GrapQL you would see exactly how
values
should be filled. You simply need to remove the double quotes around the names of the keys and than you would have the exact value of thevalues
key. Just try this and you will quickly see how this works. Even for more complexvalues
when submitting tasks.