Process “API” with event sub-processes#

This is an example, how non-interrupting event subprocess with message start event, could be used to communicate and interact with process.

[1]:
from IPython.display import display
from requests import get, post

Example process#

At first, we need to design a process with a such event sub-process:

[2]:
bpmn = open("example-sub-process.bpmn").read()
[3]:
from IPython.display import display
import json

config = {
    "style": {
        "height": "400px"
    },
    "zoom": 1.2
}
render = lambda update={}: display({
    "application/bpmn+xml": bpmn,
    "application/bpmn+json": json.dumps(config | update)
}, raw=True)
[4]:
render()
../_images/bpmn-examples_message-event-sub-process_7_0.svg

Deploying a process#

Next, we need to deploy it.

[5]:
base_url = "http://localhost:8099/engine-rest"
definition_key = "example-event-sub-process"
[6]:
post(f"{base_url}/deployment/create", files={
    "deployment-name": "Example",
    "deploy-changed-only": True,
    "deployment-source": "notebook",
    "bpmn": bpmn
}).json()
[6]:
{'links': [{'method': 'GET',
   'href': 'http://localhost:8099/engine-rest/deployment/52166322-abc1-11ed-bc3a-4e5dd88dffdb',
   'rel': 'self'}],
 'id': '52166322-abc1-11ed-bc3a-4e5dd88dffdb',
 'name': 'Example',
 'source': 'notebook',
 'deploymentTime': '2023-02-13T17:10:31.257+0000',
 'tenantId': None,
 'deployedProcessDefinitions': None,
 'deployedCaseDefinitions': None,
 'deployedDecisionDefinitions': None,
 'deployedDecisionRequirementsDefinitions': None}

Starting a new instance#

Once it’s deployed, we are able to start an instance of it:

[7]:
response = post(f"{base_url}/process-definition/key/{definition_key}/start", headers={"content-type": "application/json"}).json()
display(response)
instance_id = response["id"]
{'links': [{'method': 'GET',
   'href': 'http://localhost:8099/engine-rest/process-instance/e0b0a5c8-ac44-11ed-bc3a-4e5dd88dffdb',
   'rel': 'self'}],
 'id': 'e0b0a5c8-ac44-11ed-bc3a-4e5dd88dffdb',
 'definitionId': 'example-event-sub-process:1:52188604-abc1-11ed-bc3a-4e5dd88dffdb',
 'businessKey': None,
 'caseInstanceId': None,
 'ended': False,
 'suspended': False,
 'tenantId': None}
[8]:
render(dict(activities=get(f"{base_url}/history/activity-instance", params={"processInstanceId": instance_id}).json()))
../_images/bpmn-examples_message-event-sub-process_15_0.svg

And, as we see, the process starts without variables:

[9]:
get(f"{base_url}/process-instance/{instance_id}/variables").json()
[9]:
{'status': {'type': 'String', 'value': 'running', 'valueInfo': {}}}

Setting and querying process variables#

[10]:
import base64
message = {
    "messageName": "UpdateExampleMessage",
    "processInstanceId": instance_id,
    "processVariables": {
        "status": {
            "type": "String",
            "value": "still-running"
        },
        "message.txt": {
            "type": "File",
            "value": base64.b64encode("Hello World".encode("utf-8")).decode("UTF-8"),
            "valueInfo": { "filename": "message.txt", "mimetype": "text/plain", "encoding": "UTF-8" }
        }
    },
    "resultEnabled": True,
    "variablesInResultEnabled": True
}
[11]:
post(f"{base_url}/message", json=message).json()
[11]:
[{'resultType': 'Execution',
  'execution': {'id': 'e0b0a5c8-ac44-11ed-bc3a-4e5dd88dffdb',
   'processInstanceId': 'e0b0a5c8-ac44-11ed-bc3a-4e5dd88dffdb',
   'ended': False,
   'tenantId': None},
  'processInstance': None,
  'variables': {'message.txt': {'type': 'File',
    'value': None,
    'valueInfo': {'encoding': 'UTF-8', 'filename': 'message.txt'}},
   'status': {'type': 'String', 'value': 'still-running', 'valueInfo': {}}}}]
[12]:
get(f"{base_url}/process-instance/{instance_id}/variables").json()
[12]:
{'message.txt': {'type': 'File',
  'value': None,
  'valueInfo': {'encoding': 'UTF-8', 'filename': 'message.txt'}},
 'status': {'type': 'String', 'value': 'still-running', 'valueInfo': {}}}
[13]:
render(dict(activities=get(f"{base_url}/history/activity-instance", params={"processInstanceId": instance_id}).json()))
../_images/bpmn-examples_message-event-sub-process_22_0.svg

Triggering conditional boundary events#

[14]:
message = {
    "messageName": "UpdateExampleMessage",
    "processInstanceId": instance_id,
    "processVariables": {
        "status": {
            "type": "String",
            "value": "completed"
        }
    },
    "resultEnabled": True,
    "variablesInResultEnabled": True
}
[15]:
post(f"{base_url}/message", json=message).json()
[15]:
[{'resultType': 'Execution',
  'execution': {'id': 'e0b0a5c8-ac44-11ed-bc3a-4e5dd88dffdb',
   'processInstanceId': 'e0b0a5c8-ac44-11ed-bc3a-4e5dd88dffdb',
   'ended': True,
   'tenantId': None},
  'processInstance': None,
  'variables': {'message.txt': {'type': 'File',
    'value': None,
    'valueInfo': {'encoding': 'UTF-8', 'filename': 'message.txt'}},
   'status': {'type': 'String', 'value': 'completed', 'valueInfo': {}}}}]
[16]:
render(dict(activities=get(f"{base_url}/history/activity-instance", params={"processInstanceId": instance_id}).json()))
../_images/bpmn-examples_message-event-sub-process_26_0.svg