Save the BPMN process file.
The following is the BPMN model for applicant age evaluation in this example:
Figure 225. Examplepersons.bpmn2
BPMN processYou can continue adding or modifying any remaining components and properties of your BPMN process or create a separate example.
The following are additional BPMN models that are used with the
persons.bpmn2
process as part of the same example application:Figure 226. Exampleorders.bpmn2
processFigure 227. ExampleorderItems.bpmn2
process invoked as a subprocessAs an illustration of a more complex use case, the following is an example BPMN model from a separate mortgage loan application for determining loan approval:
Figure 228. Example business process for a mortgage loan applicationFor more Kogito examples and instructions for using them, see the
kogito-examples
repository in GitHub.
10.4. Variables in Kogito processes
Variables in Kogito processes store data that is used during runtime. The Kogito BPMN modeler supports the following types of variables:
-
Process variables: Variables that are visible within a specific process instance. Process variables are initialized at process creation and destroyed on process completion.
-
Local variables: Variables that are visible within a specific process component, such as a task. Local variables are initialized when the element context is initialized (when the execution workflow enters the node and execution of the
onEntry
action has finished, if applicable). Local variables are destroyed when the element context is destroyed (when the execution workflow leaves the element).
A BPMN component, such as a process, subprocess, or task, can only access variables in its own context or in its parent context. A component cannot access a variable defined in a child component. When a BPMN component requires access to a variable during runtime, its own context is searched first.
If the variable cannot be found directly in the component context, the immediate parent context is searched. The search continues until the process context is reached.
If the variable cannot be found, a read access request returns null
, a write access produces an error message, and the process continues its execution. Variables are searched for based on their unique ID.
10.4.1. Variable tags in BPMN process files
For greater control over variable behavior, you can tag process variables and local variables in the BPMN process file. Tags are simple string values that you add as metadata to a specific variable.
Kogito supports the following tags for process variables and local variables:
-
internal
: Sets the variable as internal only for a process instance and hides the variable from the exposed REST model. For example, you can use this tag with intermediate variables that help hold some state during the execution of the process but are not part of the domain. -
required
: Sets the variable as a requirement in order to start a process instance. If a process instance starts without the required variable, Kogito generates aVariableViolationException
error. -
readonly
: Indicates that the variable is for informational purposes only and can be set only once during process instance execution. If the value of a read-only variable is modified at any time, Kogito generates aVariableViolationException
error. -
input
: Sets the variable as an input of the process and therefore is not exposed in the returned data model. As a result, the value of an input variable is not returned in response to REST requests. -
output
: Sets the variable as an output of the process and therefore is not expected for a process start and is included in the returned data model. As a result, the value of an output variable is returned in response to REST requests. -
business-relevant
: Indicates that the variable is relevant for a particular item of business value. This tag is helpful for monitoring purposes or for implying that the variable is relevant to another application. -
tracked
: Sets a variable to be tracked for changes so that Kogito generates events anytime the value of this variable is changed. Events are published to thekogito-variables-events
topic in Kogito, where you can access the previous and new values.
You can define a variable tag in the {KOGITO} BPMN modeler in VSCode, or you can add the tag directly in the BPMN process source file as a customTags
metadata property with the tag value defined in the format ![CDATA[TAG_NAME]]
.
For example, the following BPMN process applies the required
tag to an approver
process variable:
<bpmn2:property id="approver" itemSubjectRef="ItemDefinition_9" name="approver">
<bpmn2:extensionElements>
<tns:metaData name="customTags">
<tns:metaValue><![CDATA[required]]></tns:metaValue>
</tns:metaData>
</bpmn2:extensionElements>
</bpmn2:property>
You can use multiple tags for a variable where applicable, but use caution and ensure that the tags are logical and do not conflict. For example, avoid tagging a variable as both internal
and required
.
By default, if a process variable has no tag assigned to it, Kogito assigns an input
and an output
tag to it.
You can also define custom variable tags in your BPMN files to make variable data available to Kogito process event listeners. Custom tags do not influence the Kogito runtime as the standard variable tags do and are for informational purposes only. You define custom variable tags in the same customTags
metadata property format that you use for standard Kogito variable tags.
10.4.2. Defining process variables in Kogito processes
Process variables are visible within a specific process instance. Process variables are initialized at process creation and destroyed on process completion. You can map process variables to local variables.
-
In your VSCode IDE, open the relevant BPMN process file to view the process in the Kogito BPMN modeler.
-
Select the background of the BPMN modeler canvas and, in the upper-right corner of the modeler, click Properties.
-
Under Process Data → Process Variables, click the plus icon to add a new process variable and enter the following values:
-
Name: Enter the name of the process variable, such as
order
for a process variable with order information shared by all applicable nodes in the process. -
Data Type: Enter a custom or standard data type of the variable, such as
org.acme.Order
.Figure 230. Example process variables in BPMN modeler
-
10.4.3. Defining local variables in Kogito processes
Local variables are visible within a specific process component, typically a task. Local variables are initialized when the element context is initialized (when the execution workflow enters the node and execution of the onEntry
action has finished, if applicable). Local variables are destroyed when the element context is destroyed (when the execution workflow leaves the element).
You can map local variables to global or process variables. This mapping enables you to maintain relative independence from the parent context that accommodates the local variable. This isolation helps prevent technical exceptions.
For tasks, with the exception of script tasks, you define local variables as data input or output assignments under Assignments in the task properties. Data input assignments define variables that enter the task and provide the entry data required for the task execution. Data output assignments refer to the context of the task after execution to acquire output data.
User tasks present data related to the actor who is completing the user task. User tasks also require the actor to provide result data related to the execution.
-
In your VSCode IDE, open the relevant BPMN process file to view the process in the Kogito BPMN modeler.
-
Select the relevant task (non-script task) and, in the upper-right corner of the modeler, click Properties.
-
Under Assignments, click the edit icon to open the Data I/O window, and click Add to begin adding local variables as data input or output:
-
Name: Enter the name of the data input or output, such as
person
for a local variable with person information as the input andisAdult
for a local variable with adult status as the output. -
Data Type: Enter a custom or standard data type of the data input or output, such as
org.acme.Person
. -
Source or Target: Enter the source object for the data input or the target object for the data output, such as
person
for a Java class with person information.Figure 231. Example local variables in BPMN modeler
-
10.5. Persistence in Kogito services
Kogito supports runtime persistence for preserving process data in your services, such as active process nodes and process instance variables, across application restarts. For Kogito persistence, you can use Infinispan and configure key-value storage definitions to persist data, or you can use MongoDB to persist data in a document-based format.
Runtime persistence is intended primarily for storing data that is required to resume workflow execution for a particular process instance. Persistence applies to both public and private processes that are not yet complete. Once a process completes, persistence is no longer applied. This persistence behavior means that only the information that is required to resume execution is persisted.
Node instances that are currently active or in wait states are persisted. When a process instance finishes execution but has not reached the end state (completed or aborted), the node instance data is persisted.
10.5.1. Persistence workflow in Kogito
In Kogito, a process instance is persisted when the process reaches a wait state, where the process does not execute anymore but has not reached the end state (completed or aborted).
For example, when a process reaches a user task or a catching signal event, the process instance pauses and the Kogito process engine takes a complete snapshot of the process, including the following data:
-
Process instance metadata, such as process instance ID, process definition ID, state, description, and start date
-
Process instance variables
-
Active node instances, including local variables
Process instance metadata is persisted with a predefined protobuf (protocol buffers) schema that is aware of the metadata and supports node instances that are in wait states.
Process instance and node instance variables are persisted based on the generated protobuf schema and generated marshallers. Custom data types are also persisted during execution.
For straight-through process instances that do not trigger any activity, persistence is not invoked and no data is stored.
Each process definition has its own cache for storing runtime information. The cache is based on the process definition ID and is named in the Infinispan Server or in the MongoDB Server. If no process cache exists, cache is automatically created in Infinispan or in MongoDB. This setup facilitates maintenance of process instance data and reduces concurrency on the cache instances.
10.5.2. Persisted process instance variables and data types
Persisted process variables, local variables, and other process data are stored with the process instance. The stored data is marshalled into bytes format so it can be transferred and persisted into the key-value storage definition for Infinispan or into document-based format for MongoDB. The marshalling and unmarshalling is implemented based on protobuf (protocol buffers) and requires a schema and marshallers for handling a specified type of data.
Kogito generates both the protobuf schema (as PROTO files) and marshallers for persisting variables. The Kogito marshallers are based on the ProtoStream subproject of Infinispan.
When you build your Kogito project, Kogito scans all process definitions and extracts information about the data within the business assets. Based on the unique data types (regardless of how many processes reference a specified type), a PROTO file called kogito-application.proto
is generated that builds a complete schema for the application. This file is stored in the target/classes/persistence/
folder of your project after successful build.
syntax = "proto2";
package org.kie.kogito.examples;
import "kogito-types.proto";
message Order {
option java_package = "org.kie.kogito.examples.demo";
optional string orderNumber = 1;
optional bool shipped = 2;
optional double total = 3;
}
message Person {
option java_package = "org.kie.kogito.examples.demo";
optional bool adult = 1;
optional int32 age = 2;
optional string name = 3;
}
Each kogito-application.proto file imports a kogito-types.proto file that automatically defines the base types managed by Kogito.
|
Based on the kogito-application.proto
file, marshallers are also generated and configured in the application so that whenever a particular data type is used in a process instance, the data is successfully marshalled and unmarshalled.
10.5.3. Supported data types for persisted variables
For optimal persistence with process data and variables, use Java objects as data types that represent your process variables. If you use other formats for data types, your data might not be persisted or your Kogito project might fail to compile.
Kogito currently supports the following data types for process variables:
| Data type | Description |
|---|---|
|
Basic text type |
|
Basic number type |
|
Extended size number type |
|
Basic floating point number type |
|
Extended size floating point number type |
|
Basic date type |
Java object |
Custom data type built with multiple simple types |
Java object with a Java object |
Custom data type built with multiple simple types and includes another Java object |
Java object with a list of Java objects |
Custom data type built with multiple simple types and a list of Java objects, and can also contain another Java object |
10.5.4. Enabling Infinispan persistence for Kogito services
You can enable persistence for your Kogito services using Infinispan to persist data, such as active process nodes and process instance variables, so that the data is preserved across application restarts. For Kogito persistence with Infinispan, you must have a an Infinispan Server installed and running in order to enable persistence.
-
Infinispan Server 11.0 or later is installed and running. For information about Infinispan installation and configuration, see the Infinispan documentation.
-
Add the following dependencies to the
pom.xml
file of your Kogito project:On Quarkus<dependency> <groupId>org.kie.kogito</groupId> <artifactId>infinispan-persistence-addon</artifactId> <version>KOGITO_VERSION</version> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-infinispan-client</artifactId> </dependency>
On Spring Boot<dependency> <groupId>org.kie.kogito</groupId> <artifactId>infinispan-persistence-addon</artifactId> <version>KOGITO_VERSION</version> </dependency> <dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-spring-boot-starter-remote</artifactId> <version>INFINISPAN_SPRING_BOOT_VERSION</version> </dependency>
-
Add following property to the
src/main/resources/application.properties
file in your Kogito project to configure the connection to the Infinispan Server.Replace the server host and port information according to your Infinispan Server installation.
On Quarkusquarkus.infinispan-client.server-list=localhost:11222
On Spring Bootinfinispan.remote.server-list=<IP_ADDRESS>:11222
| As an alternative to enabling Infinispan persistence explicitly in Kogito services, you can use the Kogito Operator to install the Infinispan infrastructure and enable persistence for the service during deployment on OpenShift. For more information about enabling Infinispan persistence with the Kogito Operator, see Kogito Operator interaction with Infinispan. |
For example Kogito services with Infinispan persistence, see the following example applications in GitHub:
-
process-infinispan-persistence-quarkus
: Example on Quarkus -
process-infinispan-persistence-springboot
: Example on Spring Boot
10.5.5. Enabling MongoDB persistence for Kogito services
As an alternative to using Infinispan for Kogito runtime persistence, you can enable persistence for your Kogito services using MongoDB. MongoDB is a general purpose, document-based database that enables you to store data in JSON-like documents instead of key-value storage definitions in Infinispan-based persistence storage. For Kogito persistence with MongoDB, you must have a MongoDB Server installed and running in order to enable persistence.
-
MongoDB Server 3.6 or later is installed and running. For information about MongoDB installation and configuration, see the MongoDB documentation.
-
Add the following dependencies to the
pom.xml
file of your Kogito project:On Quarkus<dependency> <groupId>org.kie.kogito</groupId> <artifactId>mongodb-persistence-addon</artifactId> <version>KOGITO_VERSION</version> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-mongodb-client</artifactId> </dependency>
On Spring Boot<dependency> <groupId>org.kie.kogito</groupId> <artifactId>mongodb-persistence-addon</artifactId> <version>KOGITO_VERSION</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> <version>MONGODB_SPRING_BOOT_VERSION</version> </dependency>
-
Add following properties to the
src/main/resources/application.properties
file in your Kogito project to configure MongoDB persistence and to connect to the relevant MongoDB Server and database.Replace the server host, port, and database information according to your MongoDB Server installation. By default, the database is named
kogito
.On Quarkuskogito.persistence.type=mongodb quarkus.mongodb.connection-string = mongodb://localhost:27017 quarkus.mongodb.database=kogito_db
On Spring Bootkogito.persistence.type=mongodb spring.data.mongodb.uri=mongodb://localhost:27017 spring.data.mongodb.database=kogito_db
After you enable MongoDB persistence for your Kogito services, you can use MongoDB tools such as MongoDB Compass to query and review the process instance information and model variables from the database, as shown in the following example:
{
"_id": "0e6c09de-938f-41f7-acdb-ecbe2e409c23",
"processInstance": {
"processType": "RuleFlow",
"id": "0e6c09de-938f-41f7-acdb-ecbe2e409c23",
"processId": "dealreviews",
"state": 1,
"nodeInstance": [
{
"id": "be9542c0-8cc3-4fbc-ac6c-f337bb176682",
"nodeId": "2",
"content": {
"type": "HUMAN_TASK_NODE",
"humanTask": {
"workItemId": "d5a61e95-9dce-472b-8dfe-dd948e086f7a",
"workitem": {
"id": "d5a61e95-9dce-472b-8dfe-dd948e086f7a",
"processInstancesId": "0e6c09de-938f-41f7-acdb-ecbe2e409c23",
"name": "Human Task",
"state": 0,
"variable": [
{
"name": "Skippable",
"strategyIndex": 0,
"value": "true",
"dataType": "java.lang.String"
},
{
"name": "deal",
"strategyIndex": 0,
"value": "my fancy deal",
"dataType": "java.lang.String"
},
{
"name": "ActorId",
"strategyIndex": 0,
"value": "john",
"dataType": "java.lang.String"
},
{
"name": "TaskName",
"strategyIndex": 0,
"value": "review",
"dataType": "java.lang.String"
},
{
"name": "NodeName",
"strategyIndex": 0,
"value": "Review the deal",
"dataType": "java.lang.String"
},
{
"name": "traveller",
"strategyIndex": 0,
"value": {
"firstName": "John",
"lastName": "Doe",
"email"<EMAIL_ADDRESS>"nationality": "American",
"address": {
"street": "main street",
"city": "Boston",
"zipCode": "10005",
"country": "US"
}
},
"dataType": "org.acme.travels.Traveller"
}
],
"nodeInstanceId": "be9542c0-8cc3-4fbc-ac6c-f337bb176682",
"nodeId": "2",
"phaseId": "active",
"phaseStatus": "Ready",
"startDate": "1598460385978",
"taskName": "review",
"potUsers": [
"john"
],
"taskReferenceName": "Review the deal"
}
}
},
"level": 1,
"slaCompliance": 0,
"triggerDate": "1598460385976"
}
],
"variable": [
{
"name": "deal",
"strategyIndex": 0,
"value": "my fancy deal",
"dataType": "java.lang.String"
},
{
"name": "traveller",
"strategyIndex": 0,
"value": {
"firstName": "John",
"lastName": "Doe",
"email"<EMAIL_ADDRESS>"nationality": "American",
"address": {
"street": "main street",
"city": "Boston",
"zipCode": "10005",
"country": "US"
}
},
"dataType": "org.acme.travels.Traveller"
}
],
"parentProcessInstanceId": "57bffb3d-06a7-48e0-87be-004a722792db",
"completedNodeIds": [
"_7E3D27D0-6644-4E55-8E41-9F68BD0D1327"
],
"iterationLevels": [
{
"id": "_3597E33A-1C00-41B3-924E-09EA47F79D93",
"level": 1
}
],
"description": "Deal Review",
"signalCompletion": true,
"slaCompliance": 0,
"rootProcessInstanceId": "57bffb3d-06a7-48e0-87be-004a722792db",
"startDate": "1598460385975",
"rootProcessId": "deals"
},
"strategies": [
{
"name": "org.kie.kogito.mongodb.marshalling.DocumentMarshallingStrategy",
"value": 0
}
]
}
For example Kogito services with MongoDB persistence, see the following example applications in GitHub:
-
process-mongodb-persistence-quarkus
: Example on Quarkus -
process-mongodb-persistence-springboot
: Example on Spring Boot
10.6. Enabling Kafka messaging for Kogito services
Kogito supports the MicroProfile Reactive Messaging specification for messaging in your services. You can enable messaging to configure message events as either input or output of business process execution.
For example, the following handle-travelers.bpmn2
process uses messaging start and end events to communicate with travelers:
In this example, the message start and end events require the following information:
-
Message name that maps to the channel that delivers messages
-
Message payload that maps to a process instance variable
For this procedure, the messaging is based on Apache Kafka as the event publisher, so you must have Kafka installed in order to enable messaging. Your marshalling configuration depends on the messaging solution that you use.
-
Apache Kafka is installed and includes any required topics. For information about Kafka installation and configuration, see the Apache Kafka documentation.
-
Add the following dependencies to the
pom.xml
file of your Kogito project:On Quarkus<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-smallrye-reactive-messaging-kafka</artifactId> </dependency>
On Spring Boot<dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency>
-
Configure the incoming and outgoing messaging channels and properties:
-
On Quarkus: Add the following properties to the
src/main/resources/application.properties
file in your Kogito project to configure the incoming and outgoing messages and channels:Configure incoming and outgoing messages and channelsmp.messaging.incoming.travellers.connector=smallrye-kafka mp.messaging.incoming.travellers.topic=travellers mp.messaging.incoming.travellers.value.deserializer=org.apache.kafka.common.serialization.StringDeserializer mp.messaging.outgoing.processedtravellers.connector=smallrye-kafka mp.messaging.outgoing.processedtravellers.topic=processedtravellers mp.messaging.outgoing.processedtravellers.value.serializer=org.apache.kafka.common.serialization.StringSerializer
Replace
travellers
with the name of the message start event. Replaceprocessedtravellers
with the name of the message end event.To prevent execution errors due to long wait times with messaging, you can also use the following property to disable waiting for message completion:
Disable message wait timemp.messaging.outgoing.[channel-name].waitForWriteCompletion=false
-
On Spring Boot: Add the following property to the
src/main/resources/application.properties
file in your Kogito project to configure the messaging channel, and create the JavaBeans for the incoming and outgoing messages:Configure messaging channelkafka.bootstrapAddress=localhost:9092
Create JavaBeans for incoming messages@EnableKafka @Configuration public class KafkaConsumerConfig { @Value(value = "${kafka.bootstrapAddress}") private String bootstrapAddress; public ConsumerFactory<String, String> consumerFactory() { Map<String, Object> props = new HashMap<>(); props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress); props.put(ConsumerConfig.GROUP_ID_CONFIG, "travellers-group"); return new DefaultKafkaConsumerFactory<>(props, new StringDeserializer(), new StringDeserializer()); } @Bean public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() { ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>(); factory.setConsumerFactory(consumerFactory()); return factory; } }
Create JavaBeans for outgoing messages@Configuration public class KafkaProducerConfig { @Value(value = "${kafka.bootstrapAddress}") private String bootstrapAddress; @Bean public ProducerFactory<String, String> producerFactory() { Map<String, Object> configProps = new HashMap<>(); configProps.put(JsonSerializer.ADD_TYPE_INFO_HEADERS, false); configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress); configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); return new DefaultKafkaProducerFactory<>(configProps); } @Bean public KafkaTemplate<String, String> kafkaTemplate() { return new KafkaTemplate<>(producerFactory()); } }
-
| As an alternative to enabling Kafka messaging explicitly in Kogito services, you can use the Kogito Operator to install the Kafka infrastructure and enable messaging for the service during deployment on OpenShift. For more information about enabling Kafka messaging with the Kogito Operator, see Kogito Operator interaction with Apache Kafka. |
For example Kogito services with Kafka messaging, see the following example applications in GitHub:
-
process-kafka-quickstart-quarkus
: Example on Quarkus -
process-kafka-quickstart-springboot
: Example on Spring Boot
10.7. Knative Eventing in Kogito services
Knative Eventing is a system that enables you to create event producers and consumers for your applications. Knative Eventing uses standard HTTP POST requests to send and receive events between event producers and consumers. These events conform to the CloudEvents specification, which enables creating, parsing, sending, and receiving events in any programming language.
Kogito provides a knative-eventing-addon
add-on that enables you to use Knative Eventing with Kogito services that consume or publish messages within a Business Process Model and Notation (BPMN) process model or Serverless Workflow. Kogito runtime events for messages, processes, tasks, and other application activities are published in CloudEvents format so that they can be consumed efficiently by other entities, such as the Knative Eventing system.
| Knative Eventing is currently supported for Kogito services on Quarkus only. The Kogito Operator supports Knative Eventing 0.17 or later. |
For example, the following handle-travelers.bpmn2
process uses messaging start and end events to communicate with travelers:
When the Knative Eventing add-on is enabled in the Kogito project that contains this example process, an event consumer is generated from the message start node and an event producer is generated from the message end node at build time.
The following diagram illustrates a scenario with Knative Eventing and a Kogito service that contains event consumers:
In this scenario, three Knative Eventing Triggers are generated to filter the messages that are received by the Kogito service. These messages are sent to the default Kogito service port. A message-routing mechanism in the generated code redirects the message to an inner channel based on the name of the message start event in the BPMN process model. The names of message start and end events serve as unique CloudEvents type
attribute definitions in Knative Eventing.
In the example handle-travlers.bpmn2
process, the message start node is named travelers
, so a message with a type
named travelers
triggers the message start node, as shown in the following example curl request:
travelers
message start event$ curl -X POST \
-H "content-type: application/json" \
-H "ce-specversion: 1.0" \
-H "ce-source: /from/localhost" \
-H "ce-type: travelers" \
-H "ce-id: 12346" \
-d '{"firstName": "Jane", "lastName": "Doe", "email"<EMAIL_ADDRESS>"nationality": "German"}' \
http://localhost:8080
The following diagram illustrates a scenario with Knative Eventing and a Kogito service that contains event producers:
In this scenario, the Kogito service sends HTTP POST messages to the Knative Eventing Broker through the SinkBinding
resource. The SinkBinding
endpoint is generated by the Knative Eventing platform and is injected in the Kogito service container as an environment variable named ${K_SINK}
.
The following example message is generated by the Kogito service:
Context Attributes,
specversion: 1.0
type: process/travelers/processedtravellers
source: /process/Travelers/2f692fd9-fff8-4b0a-bb64-96d1a4772490
id: 29e43b17-3a70-4b46-aca0-7ab8e2133eee
time: 2020-08-10T20:52:39.383346Z
Extensions,
knativearrivaltime: 2020-08-10T20:52:39.391404032Z
knativehistory: default-kne-trigger-kn-channel.kogito.svc.cluster.local
kogitoprocessid: Travelers
kogitoprocessinstanceid: 2f692fd9-fff8-4b0a-bb64-96d1a4772490
kogitoprocessinstancestate: 1
Data,
{"firstName":"Jan","lastName":"Kowalski","email":"jan.kowalski@example.com","nationality":"German","processed":true}
In this case, the CloudEvents type
attribute uses the format process/PROCESS_ID/NODE_NAME
. This format prevents the messages generated by the Kogito service from conflicting with other messages being generated within the cluster, and enables the SinkBinding
objects to filter these messages by a unique type
. The generated CloudEvents message also contains information about the process instance, such as the process ID, process instance ID, and process instance state.
The following diagram illustrates the overall architecture of a Kogito service deployed in a Knative Eventing environment on a Kubernetes or OpenShift cluster:
10.7.1. Enabling Knative Eventing for Kogito services
You can enable Knative Eventing support for Kogito services that consume or publish messages within a Business Process Model and Notation (BPMN) process model. When you enable Knative Eventing for a Kogito project, event consumers and producers are generated from message start and end nodes in BPMN processes at build time. You can use these event consumers and producers as part of your Kogito service deployment in a Knative Eventing environment on Kubernetes or OpenShift clusters.
| Knative Eventing is currently supported for Kogito services on Quarkus only. The Kogito Operator supports Knative Eventing 0.17 or later. |
-
You have installed and deployed Knative Eventing 0.17 or later on a Kubernetes or an OpenShift cluster. For information about Knative Eventing on OpenShift, see Installing Knative Eventing in the OpenShift documentation.
-
You have created a BPMN model in your Kogito project with message start or end events that you want to integrate with Knative Eventing. For information about creating BPMN models, see Creating and editing BPMN models in the Kogito BPMN modeler.
-
Add the following dependencies to the
pom.xml
file of your Kogito project:Knative Eventing dependencies<dependencies> <dependency> <groupId>org.kie.kogito</groupId> <artifactId>knative-eventing-addon</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-smallrye-reactive-messaging</artifactId> </dependency> <dependency> <groupId>io.smallrye.reactive</groupId> <artifactId>smallrye-reactive-messaging-http</artifactId> </dependency> </dependencies>
These dependencies enable Knative Eventing add-on and messaging requirements. When a Kogito service has the Knative Eventing add-on enabled, Kogito generates code based on Smallrye Reactive Messaging to publish messages.
-
In your Kogito project, open the BPMN file that you want to use for consuming or producing messages in the Knative Eventing environment. BPMN files are typically in
src/main/resources
.For example, the following
handle-travelers.bpmn2
process uses messaging start and end events to communicate with travelers:Figure 239. Example process with messaging start and end eventsThe names of message start and end events serve as CloudEvents
type
attribute definitions in Knative Eventing and must be unique. -
For each message event in the BPMN process model, select the node, click Properties in the upper-right corner of the modeler, and verify that the node name is clear and unique.
For example, consider adding the project or process name as a prefix to the message node name, such as
travelagency.travelers
in the following example:Figure 240. Set a unique message node name -
After you verify and save the message node names, navigate to the
src/main/resources/application.properties
file in your Kogito project and add the following properties for every message node that publishes messages:Required application properties for every publishing message nodemp.messaging.outgoing.MESSAGE_NODE_NAME.connector=smallrye-http mp.messaging.outgoing.MESSAGE_NODE_NAME.url=${K_SINK}
Replace
MESSAGE_NODE_NAME
with the name of the message node that publishes messages, typically a message end event. Every message node that publishes messages must have these properties set. Incoming (subscribed) message nodes do not require any configuration.The
smallrye-http
property defines the HTTP endpoint for the published messages. The${K_SINK}
property is an environment variable injected by Knative Eventing when you deploy a Kogito service that references a Knative EventingSinkBinding
object. -
Build your Kogito project locally using your usual method, such as
mvn clean package
, and navigate to thetarget/generated-sources/kogito
directory in your project and verify the following contents:-
Generated classes with the suffixes
MessageConsumer
andMessageProducer
. These classes are generated based on the message start and end events in your BPMN model. -
Generated
app
folder containing aCloudEventListenerResource.java
file. This file detects any CloudEvents messages produced by the Knative Eventing source that targets your Kogito service.
If any of these items are missing, ensure that you have configured all required dependencies, applications properties, and message event name. After all checks are complete, rebuild the project.
-
-
After you configure and test your Kogito project locally, in your Kubernetes or OpenShift environment, add the following custom resources to prepare your Kogito project for deployment. These resources enable the Kogito Operator to generate the required resources for consuming or producing events in a Knative Eventing environment.
-
Broker
: When you deploy a Kogito service that uses theknative-eventing-addon
add-on, you must also deploy a Knative Eventing Broker in the same namespace. The Kogito service uses this Broker to publish or listen to CloudEvents messages. You can use any Broker channel for the Kogito service, such as InMemoryChannel, KafkaChannel, or NatssChannel.By default, the InMemoryChannel channel is used when no channel is specified, as shown in the following
Broker
custom resource example:ExampleBroker
custom resource for Knative Eventing with default InMemoryChannelapiVersion: eventing.knative.dev/v1 kind: Broker metadata: name: default
InMemoryChannel channels are for development use only. Do not use this channel in a production deployment. For more information about available Broker channels and how to install them, see Available Channels in the Knative documentation.
-
KogitoInfra
: To bind the Knative Eventing Broker instance to the Kogito service being deployed, you must create aKogitoInfra
instance, as shown in the following example:ExampleKogitoInfra
custom resource for a Kogito service withBroker
bindingapiVersion: app.kiegroup.org/v1alpha1 kind: KogitoInfra metadata: name: kogito-knative-infra spec: # Bind Knative Broker to the service resource: apiVersion: eventing.knative.dev/v1 kind: Broker name: default
-
KogitoRuntime
: TheKogitoRuntime
resource used to deploy the Kogito service using the Kogito Operator must have thisKogitoInfra
instance linked to it, as shown in the following example:ExampleKogitoRuntime
custom resource for a Kogito service withKogitoInfra
bound to itapiVersion: app.kiegroup.org/v1alpha1 kind: KogitoRuntime metadata: name: process-knative-quickstart-quarkus spec: replicas: 1 image: quay.io/NAME_SPACE/process-knative-quickstart-quarkus:latest # Reference to the KogitoInfra resource with the Knative Broker binding infra: - kogito-knative-infra
After you apply these resources to the Kubernetes or OpenShift namespace, if any BPMN or Serverless Workflow files in the Kogito project contain events to be consumed or produced, the Kogito Operator automatically creates the required Knative Eventing
Trigger
resource for consuming events and theSinkBinding
resource for producing events.The following is an example
Trigger
resource generated by the Kogito Operator:ExampleTrigger
custom resource generated by the operator (consuming)apiVersion: eventing.knative.dev/v1 kind: Trigger metadata: name: travelers-trigger spec: # The default Broker is enabled in the cluster because the namespace is labeled with `knative-eventing-injection=enabled`. broker: default filter: attributes: # Name of the message node in the process. type: travelers # The subscriber is the deployed service. Any event that matches the filter in the Broker is sent here. subscriber: ref: apiVersion: v1 kind: Service name: process-knative-quickstart-quarkus
This Knative Eventing Trigger resource filters all messages delivered to the default Broker and sends them to the default service deployed by the Kogito Operator.
The following is an example
SinkBinding
resource generated by the Kogito Operator:ExampleSinkBinding
custom resource generated by the operator (producing)apiVersion: sources.knative.dev/v1alpha1 kind: SinkBinding metadata: name: process-knative-quickstart-quarkus-sink spec: subject: apiVersion: apps/v1 kind: Deployment selector: matchLabels: app: process-knative-quickstart-quarkus # Any cloud event produced by the application is delivered to the Broker. sink: ref: apiVersion: eventing.knative.dev/v1 kind: Broker name: default
This Knative Eventing
SinkBinding
resource injects the${K_SINK}
environment variable to theDeployment
resource created by the Kogito Operator. Every message produced by the Kogito service is redirected to the default Knative Broker.If you deploy your Kogito services without the Kogito Operator, you must create these Trigger
andSinkBinding
resources manually.If any other components need to consume the messages produced by the Kogito service, you must create an additional Knative Eventing
Trigger
resource as shown in the following example:Custom resource for other consuming componentsapiVersion: eventing.knative.dev/v1 kind: Trigger metadata: name: event-display-trigger spec: # The default Broker is enabled in the namespace. broker: default filter: # Listens only to events of type `success` emitted by the CloudEvents-processing service. attributes: # The same type being generated by the custom service. type: /process/travelers/processedtravellers # The subscriber is the deployed displayer service. Any event that matches the filter in the Broker is sent here. subscriber: ref: apiVersion: serving.knative.dev/v1 kind: Service name: event-display
The
spec.filter.attributes.type
value defined in theTrigger
resource is the same as the value generated by the Kogito service. -
For an example Kogito service with Knative Eventing enabled, see the process-knative-quickstart-quarkus
example application.
10.8. Task lifecycle in Kogito processes
In Kogito business processes, tasks are implemented as work items and their execution is defined by work item handlers. User tasks in particular are a core construct in Kogito processes. When a user task is reached in a process, the task progresses through phases of a defined lifecycle until it reaches an end state.
Kogito supports the following default phases in a work item (task) lifecycle:
-
Active: Indicates initial state when the work item is activated
-
Abort: Indicates abnormal completion of the work item
-
Complete: Indicates normal completion of the work item
-
Claim: Assigns the work item to a specific actor, restricting access to anyone else
-
Release: Unassigns the work item from a specific actor, releasing it to any other potential user or group to work on it (by claiming or completing)
-
Skip: Skips the work item
With Kogito, you can also add custom lifecycles and lifecycle phases to meet your business needs.
A lifecycle moves a work item across various phases that are not defined by the WorkItem
interface and defines the behavior of a work item at runtime. You typically add a lifecycle on top of the WorkItemHandler
interface so that the lifecycle is pluggable with more flexible runtime characteristics.
The WorkItemHandler
interface provides the option to move between task phases, as shown in the following method example:
public void transitionToPhase(WorkItem workItem, WorkItemManager manager, Transition<?> transition)
| This method is a default method that does nothing when not implemented. This functionality maintains backward compatibility with existing work item handler implementations. |
You typically implement the transitionToPhase
method as shown in the following example:
@Override
public void transitionToPhase(WorkItem workItem, WorkItemManager manager, Transition<?> transition) {
lifeCycle.transitionTo(workItem, manager, (Transition<Map<String, Object>>) transition);
}
The lifeCycle
element is an implementation of org.kie.kogito.process.workitem.LifeCycle<T>
that defines the execution semantics.
10.8.1. User task authorization
The org.jbpm.process.instance.impl.humantask.BaseHumanTaskLifeCycle
implementation in Kogito ensures that a user task is worked on by authorized users, based on the user or group assignments that you provide.
You can use the following parameters to provide assignments for authorized users or groups in the relevant BPMN process model. All of the listed parameters support expressions.
| Parameter name | Description | Example value |
|---|---|---|
|
Comma-separated list of authorized users |
|
|
Comma-separated list of authorized groups of users |
|
|
Comma-separated list of authorized administrators |
|
|
Comma-separated list of groups of administrators |
|
|
Comma-separated list of unauthorized users who cannot work on this task |
|
| Authorization is only enforced when the method that calls the work item lifecycle methods uses a security context. This security behavior is dependent on the API that you use. |
10.8.2. API interaction with task lifecycle phases
The following example API interacts with user tasks (work items) using lifecycle phases:
// Start process instance
ProcessInstance<?> processInstance = approvalsProcess.createInstance(m);
processInstance.start();
// Set up security policy with identity information
StaticIdentityProvider identity = new StaticIdentityProvider("admin", Collections.singletonList("managers"));
SecurityPolicy policy = SecurityPolicy.of(identity);
// Get list of work items, taking security restrictions into account
List<WorkItem> workItems = processInstance.workItems(policy);
// Work on a task
final String wiId = workItems.get(0).getId();
processInstance.transitionWorkItem(wiId,
new HumanTaskTransition(Claim.ID, null, policy));
processInstance.transitionWorkItem(wiId,
new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", false), policy));
When you interact with user tasks through a REST API, you can also provide the following query parameters for user and group information:
| Parameter name | Description | Multi-value support |
|---|---|---|
|
User name to be used for the user task authorization check |
No |
|
Zero or more group names to be used for the user task authorization check |
Yes |
For example, the following REST endpoints interact with user tasks in an orderItems.bpmn2
process for verifying customer orders:
curl -X GET http://localhost:8080/orderItems/66c11e3e-c211-4cee-9a07-848b5e861bc5/tasks
{"62f1c985-d31c-4ead-9906-2fe8d05937f0":"Verify order"}
curl -X GET http://localhost:8080/orderItems/66c11e3e-c211-4cee-9a07-848b5e861bc5/Verify_order/62f1c985-d31c-4ead-9906-2fe8d05937f0
{"id":"62f1c985-d31c-4ead-9906-2fe8d05937f0","input1":{"orderNumber":"12345","shipped":false,"total":0.537941914075738},"name":"Verify order"}
curl -X POST http://localhost:8080/orderItems/66c11e3e-c211-4cee-9a07-848b5e861bc5/Verify_order/62f1c985-d31c-4ead-9906-2fe8d05937f0?group=managers&user=john -H "accept: application/json" -H "content-type: application/json"
{"id":"66c11e3e-c211-4cee-9a07-848b5e861bc5","order":{"orderNumber":"12345","shipped":false,"total":0.537941914075738}}
10.8.3. Creating a custom task lifecycle and phase
You can extend the user task lifecycle and lifecycle phases in Kogito to implement a custom lifecycle and phases as needed.
-
To add custom lifecycle phases, implement the
org.kie.kogito.process.workitem.LifeCyclePhase
resource in the Java class for your custom lifecycle phases.This resource implements the following key methods:
-
id
: Assigns a unique ID that is used when transitioning through phases -
canTransition
: Provides a checkpoint between phases, if this phase can be transitioned from a specified phase -
status
: Defines a human-readable status for this phase -
isTerminating
: Determines if this phase is a completion stage, and if so, completes the work item and moves on to the next activity in the process -
apply
: Enables additional updates to the work item when transitioning through phases
You can implement as many phases as needed or extend existing phases.
-
-
To add a custom lifecycle, implement the
org.kie.kogito.process.workitem.LifeCycle<Map<String, Object>>
resource in the Java class for your custom lifecycle.To support user tasks, the parameterized type LifeCycle
must beMap<String, Object>
.This resource implements the following key methods:
-
phaseById
: Retrieves the lifecycle phase by ID to verify if the phase is supported by the lifecycle implementation -
phases
: Returns all supported phases by a specified lifecycle implementation -
transitionTo
: Provides the main logic to handle phase transition -
data
: Returns the current state of data for the work item
The following is an example Java class that extends the
Complete
lifecycle phase from a custom lifecycle implementation:Example Java class to extend theComplete
lifecycle phasepackage org.acme.travels.usertasks; import java.util.Arrays; import java.util.List; import org.jbpm.process.instance.impl.workitem.Complete; import org.kie.kogito.process.workitem.LifeCyclePhase; public class CompleteStartedOnly extends Complete { private List<String> allowedTransitions = Arrays.asList(Start.ID); @Override public boolean canTransition(LifeCyclePhase phase) { return allowedTransitions.contains(phase.id()); } }
-
-
After you implement your custom lifecycle or lifecycle phases, create a Java configuration class to enable the process engine to use the new lifecycle or phase instead of the default lifecycle.
In this configuration, you use the
WorkItemHandlerConfig
class as you do for any other work item handler, as shown in the following example:Example configuration class for a custom lifecycle phase@ApplicationScoped public class CustomWorkItemHandlerConfig extends DefaultWorkItemHandlerConfig { { register("Human Task", new HumanTaskWorkItemHandler(new CustomHumanTaskLifeCycle())); } }
The work item handler is the same as the default, but instead of the default lifecycle, you pass as a constructor argument the custom implementation of the
LifeCycle
interface.
For example Kogito services with custom task lifecycle configurations, see the following example applications in GitHub:
-
process-usertasks-custom-lifecycle-quarkus
: Example on Quarkus -
process-usertasks-custom-lifecycle-springboot
: Example on Spring Boot
10.9. Flexible processes for case management in Kogito
Kogito does not support the Case Management Model and Notation (CMMN) specification for case management in process services. Instead, Kogito uses Business Process Model and Notation (BPMN) extensions to provide similar case-management functionality through flexible processes.
A flexible process in Kogito is any process definition that uses ad hoc components or other features that enable the process to be executed more flexibly than traditional processes. For example, a flexible process does not require a standard start event and does not require all nodes to be connected. Some of the typical components in flexible processes include the Ad-Hoc
process property that enables the process to use ad hoc auto-start fragments and to not require strict start and end events, ad hoc subprocesses that contain embedded inner activities within another process, and milestones that flag or trigger tasks and events.
Similar to case files in CMMN, flexible processes enable you to define traditional processes with more flexibility when the execution path is not rigid. This flexibility is helpful when the process cannot be fully automated or when the scope of the process is difficult to measure. A typical example of a case or flexible process is related to healthcare. A patient has a file that is accessible to the doctor and to any health professionals (or knowledge workers) who are assigned to the patient. These assigned workers take action and make different decisions and assessments until the patient is diagnosed and treated, completing the case or flexible process.
Kogito currently supports the following key case-related features in flexible processes:
-
Ad hoc processes: An ad hoc process is any process definition that has the
Ad-Hoc
property enabled in the process diagram Properties panel. This property enables the process to use ad hoc auto-start fragments, such as ad hoc subprocesses and ad hoc tasks, and to not require strict start and end events. An ad hoc process is similar to a Case in CMMN.Figure 241. Ad hoc process property -
Ad hoc subprocesses: An ad hoc subprocess contains embedded inner activities within another process and is a standard BPMN component that is supported in Kogito. An ad hoc subprocess is similar to a Stage in CMMN.
Figure 242. Ad hoc subprocess node -
Ad hoc auto-start fragments: An ad hoc auto-start fragment is any ad hoc process, ad hoc subprocess, or ad hoc task with the
AdHoc Autostart
property enabled. This property enables the fragment to automatically start when the process is created instead of being started by the completion of the previous node or by a signal event.Figure 243. Ad hoc auto-start property -
Milestones: A milestone is a standard CMMN component that is incorporated in Kogito as a BPMN custom task. A milestone represents a single point of achievement within a process instance. You can use milestones to flag certain events to trigger other tasks or track the progress of the process.
Figure 244. Milestone node -
REST API requests as signals: A REST API request can serve as a signal event to trigger milestones or to create and start ad hoc fragments such as ad hoc processes, ad hoc subprocesses, or tasks. For non-flexible processes, an empty
POST
request for a process triggers the start node, whereas in a flexible process, the request creates the process instance. Similarly for ad hoc tasks, an emptyPOST
request instantiates the task node. All ad hoc auto-start fragments with theAdHoc Autostart
property enabled are started automatically when the process is created.Example curl request to add comments to a ticketcurl -D -XPOST -H 'Content-Type:application/json' -H 'Accept:application/json' http://localhost:8080/serviceDesk/b3c75b24-2691-4a76-902c-c9bc29ea076c/ReceiveSupportComment
Example response (JSON)HTTP/1.1 201 Created Content-Length: 305 Location: http://localhost:8080/serviceDesk/b3c75b24-2691-4a76-902c-c9bc29ea076c/ReceiveSupportComment/f3b36cf9-3953-43ae-afe6-2a48fea8a79a Content-Type: application/json { "id":"b3c75b24-2691-4a76-902c-c9bc29ea076c", "supportCase":{ "product": { "name":"Kogito", "family":"Middleware" }, "description":"Kogito is not working for some reason.", "engineer":"kelly", "customer":"Paco the customer", "state":"WAITING_FOR_OWNER", "comments":null, "questionnaire":null }, "supportGroup":"Kogito" }
10.9.1. Flexible process example
A typical flexible process consists of one or more of the following basic components:
-
Optional start event (might or might not be explicit)
-
Optional node connections (might or might not connect all nodes)
-
Enabled
Ad-Hoc
process property -
One or more subprocesses, typically ad hoc subprocesses
-
Ad hoc auto-start fragments, such as ad hoc subprocesses or ad hoc tasks
-
Milestones that flag or trigger events
-
End event to terminate the process
The following example is a real-world BPMN model scenario that demonstrates how you can use flexible processes for case management. In this scenario, a service desk uses a flexible process for handling customer tickets related to problems or questions about a specific product.
This example is based on the flexible-process-quarkus application in the kogito-examples repository in GitHub. However, this example may differ from the exact example source code as Kogito continues to be developed. Be sure to explore this and other Kogito examples in GitHub to help you develop your own applications.
|
service-desk.bpmn2
flexible processTo start the process and generate a ticket, a user provides an initial supportCase
object in a REST request that contains information about the product, the customer, and the related issue:
{
"supportCase": {
"customer": "Paco the customer",
"description": "Kogito is not working for some reason.",
"product": {
"family": "Middleware",
"name": "Kogito"
}
}
}
After the ticket is generated, the Triage
ad hoc subprocess is automatically started and the ticket is assigned to a support team and then to a support engineer. If the system cannot determine which team to assign the ticket to, a user assigns the ticket manually to a support engineer.
The decision logic for the Triage
subprocess is defined in the following SupportGroup
decision table in the triage.dmn
Decision Model and Notation (DMN) model:
SupportGroup
DMN decision tableThe Work case
ad hoc subprocess is also automatically started when the process is created. Anyone from the customer
and support
groups can add comments. To create a task that can be used to add a comment, a user can send an empty POST
request as shown in the following example:
curl -D -XPOST -H 'Content-Type:application/json' -H 'Accept:application/json' http://localhost:8080/serviceDesk/b3c75b24-2691-4a76-902c-c9bc29ea076c/ReceiveSupportComment
HTTP/1.1 201 Created
Content-Length: 305
Location: http://localhost:8080/serviceDesk/b3c75b24-2691-4a76-902c-c9bc29ea076c/ReceiveSupportComment/f3b36cf9-3953-43ae-afe6-2a48fea8a79a
Content-Type: application/json
{
"id":"b3c75b24-2691-4a76-902c-c9bc29ea076c",
"supportCase":{
"product": {
"name":"Kogito",
"family":"Middleware"
},
"description":"Kogito is not working for some reason.",
"engineer":"kelly",
"customer":"Paco the customer",
"state":"WAITING_FOR_OWNER",
"comments":null,
"questionnaire":null
},
"supportGroup":"Kogito"
}
A user can then use the URL in the Location
HTTP header when rendering the form action
, as shown in the following example:
<form action="http://localhost:8080/serviceDesk/b3c75b24-2691-4a76-902c-c9bc29ea076c/ReceiveSupportComment/f3b36cf9-3953-43ae-afe6-2a48fea8a79a" method="post">
<label for="comment">Comment:</label>
<input type="text" id="comment" name="comment">
</form>
After the customer is satisfied with the ticket response and actions, a user clicks a Resolve Case button, which sends an empty POST
request to the service task to set the case to Resolved
and the process emits a CaseResolved
event. This event signals the CaseResolved
milestone, which starts the Close
ad hoc subprocess that sends, receives, and saves the customer questionnaire and closes the case.
10.10. Kogito process management add-on
Kogito provides a process-management-addon
add-on that enables basic REST operations that you can use to manage process instances. These REST operations are supplemental to any other specific REST operations that you have configured in your application.
To configure process management REST capabilities for your Kogito services, you can add the process management add-on as a dependency in the pom.xml
file of your Kogito project:
<dependency>
<groupId>org.kie.kogito</groupId>
<artifactId>process-management-addon</artifactId>
</dependency>
The Kogito process management add-on provides REST support for the following basic operations:
-
Process instances: Abort an active process instance
-
Node instances: Cancel or re-trigger a node instance, or trigger a new node instance
-
Error handling: Retrieve error details for a process instance, or skip or re-trigger a failed node instance
In addition to exposed REST operations, the process management add-on also provides the following REST exception mappers to generate more meaningful error messages for typical exception types:
-
ProcessInstanceNotFound
-
NodeInstanceNotFound
-
NodeNotFound
-
ProcessInstanceExecutionError
-
NotAuthorized
-
InvalidTransition
(for work items) -
InvalidLifeCyclePhase
(for work items)
These exception mappers produce a valid HTTP error code with JSON payload with the context that caused the exception.
For example, the following is a ProcessInstanceNotFoundException
error generated at runtime:
HTTP code : 404
{
"processInstanceId" : "c6862071-0f2e-4f21-9bc8-586245a76c3aa",
"message" : "Process instance with id c6862071-0f2e-4f21-9bc8-586245a76c3aa not found"
}
10.10.1. REST endpoints for the process management add-on
After you add the process-management-addon
dependency to your Kogito project and run your Kogito services, you can use the following REST endpoints to manage your process and node instances. These REST operations are supplemental to any other specific REST operations that you have configured in your application.
For each endpoint, use a REST client, curl utility, or Swagger UI (if configured for the application) to send requests with the following components:
-
Base URL:
http://HOST:PORT/management/processes/PROCESS_ID/instances/PROCESS_INSTANCE_ID
-
Request parameters:
-
PROCESS_ID
: The string identifier of the process definition, such asorders
-
PROCESS_INSTANCE_ID
: The integer identifier of the process instance, such asec44f890-d21d-444f-a4ec-cb88589bd79
-
NODE_ID
: The string identifier of the node, such asverifyOrders
-
NODE_INSTANCE_ID
: The integer identifier of the node instance, such as6e46bec2-0273-46f6-ad7d-2ff156e55a6c
-
-
HTTP headers:
-
accept
:application/json
-
content-type
:application/json
-
-
HTTP methods:
GET
,POST
, orDELETE
<IP_ADDRESS>. Process instances
Use the following REST endpoints from the process management add-on to interact with process instances:
- Return active node instances for a process instance
-
[GET] /management/processes/PROCESS_ID/instances/PROCESS_INSTANCE_ID/nodeInstances
Example REST endpointhttp://localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a/nodeInstances
Example curl requestcurl -X GET localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a/nodeInstances -H 'content-type: application/json' -H 'accept: application/json'
Example response (JSON){ "id": "ec44f890-d21d-444f-a4ec-cb88589bd79a", "name": "Verify order", "nodeInstanceId": "6e46bec2-0273-46f6-ad7d-2ff156e55a6c", "parameters": { "Locale": "en-UK", "TaskName": "Verify order", "NodeName": "Verify order", "Priority": "1", "input1": { "orderNumber": "12345", "shipped": false, "total": 0.8233575052440095 }, "Skippable": "true", "ActorId": "john" }, "phase": "active", "phaseStatus": "Ready", "results": {}, "state": 0 }
- Abort a process instance
-
[DELETE] /management/processes/PROCESS_ID/instances/PROCESS_INSTANCE_ID
Example REST endpointhttp://localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a
Example curl requestcurl -X DELETE localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a -H 'content-type: application/json' -H 'accept: application/json'
<IP_ADDRESS>. Nodes
Use the following REST endpoint from the process management add-on to interact with process nodes:
- Return nodes from a process
-
[GET] /management/processes/PROCESS_ID/nodes
Example REST endpointhttp://localhost:8080/management/processes/orders/nodes
Example curl requestcurl -X GET localhost:8080/management/processes/orders/nodes -H 'content-type: application/json' -H 'accept: application/json'
Example response (JSON)[ { "name": "End", "id": 1, "type": "EndNode", "uniqueId": "1" }, { "name": "End", "id": 2, "type": "EndNode", "uniqueId": "2" }, { "name": "Hello2", "id": 3, "type": "HumanTaskNode", "uniqueId": "3" }, { "name": "Split", "id": 4, "type": "Split", "uniqueId": "4" }, { "name": "End", "id": 5, "type": "EndNode", "uniqueId": "5" }, { "name": "End", "id": 6, "type": "EndNode", "uniqueId": "6" }, { "name": "Hello1", "id": 7, "type": "HumanTaskNode", "uniqueId": "7" }, { "name": "Start", "id": 8, "type": "StartNode", "uniqueId": "8" }, { "name": "BoundaryEvent", "id": 9, "type": "BoundaryEventNode", "uniqueId": "9" }, { "name": "BoundaryEvent", "id": 10, "type": "BoundaryEventNode", "uniqueId": "10" } ]
<IP_ADDRESS>. Node instances
Use the following REST endpoints from the process management add-on to interact with node instances:
- Cancel a node instance within a process instance
-
[DELETE] /management/processes/PROCESS_ID/instances/PROCESS_INSTANCE_ID/nodeInstances/NODE_INSTANCE_ID
Example REST endpointhttp://localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a/nodeInstances/6e46bec2-0273-46f6-ad7d-2ff156e55a6c
Example curl requestcurl -X DELETE localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a/nodeInstances/6e46bec2-0273-46f6-ad7d-2ff156e55a6c -H 'content-type: application/json' -H 'accept: application/json'
- Re-trigger a node instance within a process instance
-
[POST] /management/processes/PROCESS_ID/instances/PROCESS_INSTANCE_ID/nodeInstances/NODE_INSTANCE_ID
Example REST endpointhttp://localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a/nodeInstances/6e46bec2-0273-46f6-ad7d-2ff156e55a6c
Example curl requestcurl -X POST localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a/nodeInstances/6e46bec2-0273-46f6-ad7d-2ff156e55a6c -H 'content-type: application/json' -H 'accept: application/json'
- Trigger a new instance of a node within a process instance
-
[POST] /management/processes/PROCESS_ID/instances/PROCESS_INSTANCE_ID/nodes/NODE_ID
Example REST endpointhttp://localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a/nodes/verifyOrder
Example curl requestcurl -X POST localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a/nodes/verifyOrder -H 'content-type: application/json' -H 'accept: application/json'
<IP_ADDRESS>. Error handling
Use the following REST endpoints from the process management add-on to troubleshoot errors with process and node instances:
These endpoints function only when a process instance is in an ERROR state.
|
- Return error details for a process instance
-
[GET] /management/processes/PROCESS_ID/instances/PROCESS_INSTANCE_ID/error
Example REST endpointhttp://localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a/error
Example curl requestcurl -X GET localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a/error -H 'content-type: application/json' -H 'accept: application/json'
Example response (JSON){ "processInstanceId" : "ec44f890-d21d-444f-a4ec-cb88589bd79a", "message" : "Process instance with id c6862071-0f2e-4f21-9bc8-586245a76c3aa contains no input assignment" }
- Re-trigger any failed nodes within a process instance
-
[POST] /management/processes/PROCESS_ID/instances/PROCESS_INSTANCE_ID/retrigger
Example REST endpointhttp://localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a/retrigger
Example curl requestcurl -X POST localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a/retrigger -H 'content-type: application/json' -H 'accept: application/json'
- Skip any failed nodes within a process instance
-
[POST] /management/processes/PROCESS_ID/instances/PROCESS_INSTANCE_ID/skip
Example REST endpointhttp://localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a/skip
Example curl requestcurl -X POST localhost:8080/management/processes/orders/instances/ec44f890-d21d-444f-a4ec-cb88589bd79a/skip -H 'content-type: application/json' -H 'accept: application/json'
10.11. Kogito Management Console
The Kogito Management Console is a user interface for viewing the state of all available Kogito services and managing process instances:
You can use the Management Console to view process, subprocess, and node instance details, abort process instances, and view domain-specific process data.
The Management Console requires your Kogito services to use the following Kogito components:
-
Kogito Data Index Service: Enables the Management Console to access stored events related to processes and domain data from your Kogito services. The Kogito Data Index Service requires Infinispan persistence and Apache Kafka messaging for your Kogito service. For more information about the Data Index Service, see Kogito Data Index Service.
-
Kogito process management add-on: Enables the Management Console to interact with the process data from your Kogito services through the add-on REST endpoint
/management/processes
. If you do not enable this add-on for your Kogito service, the Management Console provides read-only access to your service data without the ability to modify instances, such as aborting process instances. For more information about the process management add-on, see Kogito process management add-on.
10.11.1. Using the Kogito Management Console to manage process instances
You can use the Kogito Management Console to view and manage process instance details from your Kogito services. You can run the Management Console for local Kogito services or add it to your Kogito infrastructure on OpenShift.
-
A Kogito Data Index Service instance is configured and running for your Kogito service. The Data Index Service enables the Management Console to access stored process data. The Data Index Service requires Infinispan persistence and Apache Kafka messaging for your Kogito service. For information about the Data Index Service, see Kogito Data Index Service.
-
The
pom.xml
file of your Kogito project contains the following dependency for the process management add-on. This add-on enables the Management Console to interact with the process data through the add-on REST endpoint/management/processes
. For more information about the process management add-on, see Kogito process management add-on.Project dependency to enable process management REST operations<dependency> <groupId>org.kie.kogito</groupId> <artifactId>process-management-addon</artifactId> </dependency>
-
The
application.properties
file of your Kogito project contains the following system properties for the location where the Kogito service is deployed, such ashttp://localhost:8080
, and for Quarkus Cross-Origin Resource Sharing (CORS) support. These properties enable the Management Console to generate the URLs to execute the REST operations from the process management add-on.Application properties for REST URLskogito.service.url=http://HOST:PORT quarkus.http.cors=true
-
Go to the
management-console
artifacts page, select the latest release of the Kogito Management Console, and download themanagement-console-VERSION-runner.jar
file to a local directory. -
In a command terminal, navigate to the directory location of the downloaded
management-console-VERSION-runner.jar
file and enter the following command to run the Management Console:Running the Management Console$ java -Dquarkus.http.port=8280 -jar management-console-VERSION-runner.jar
The default port for the Management Console is 8080, but this example specifies port 8280 to avoid conflicts with the example Kogito service running at port 8080.
Also, the Management Console uses the default Data Index Service port 8180. If you modified this port in your Data Index Service instance, you must also modify the port in the Management Console properties by using the start-up property
-Dkogito.dataindex.http.url=http://HOST:PORT
when you run the Management Console.To change the logging level of the Management Console, such as for debugging, you can specify the following start-up properties:
Modifying Management Console logging level for debugging$ java \ -Dquarkus.log.console.level=DEBUG -Dquarkus.log.category.\"org.kie.kogito\".min-level=DEBUG \ -Dquarkus.log.category.\"org.kie.kogito\".level=DEBUG \ -Dquarkus.http.port=8280 \ -jar management-console-VERSION-runner.jar
In an OpenShift environment, you can use the Kogito command-line interface (CLI) or the OpenShift web console to add the Management Console to your Kogito infrastructure:
Adding the Management Console to your OpenShift infrastructure using the Kogito CLI$ kogito install mgmt-console -p PROJECT_NAME
Figure 248. Kogito Management Console instance on OpenShift web console -
In a web browser, navigate to
http://localhost:8280
to open the Management Console. If you modified the configured Management Console port, use the modified location.On OpenShift, navigate to the route URL for the Management Console instance.
Figure 249. Kogito Management ConsoleIn this example, the Management Console displays data for the
kogito-travel-agency
extended example application in thekogito-examples
repository in GitHub. -
In the Management Console, use the following pages from the left menu to interact with your process instances and data:
-
Process Instances: Use this page to view and filter process and subprocess instances by status or business key. You can select a specific process instance name to view process details or abort, skip, or retry the process. You can also select the check box for multiple instances and use the bulk operation options at the top of the screen.
Figure 250. Expanded process with subprocessesFigure 251. Details for a selected process instanceFor process instances in an error state, you can select the Error icon to view error details and skip or retry the process instance. You can also select the process instance name to view the exact node instance in the process Timeline where the error occurred and skip or retry the specific node instance.
Figure 252. Skip or retry a process instance with an errorFigure 253. Node instance with an error in a selected processFigure 254. Skip or retry a node instance with an errorYou can also cancel or retrigger active nodes in the process Timeline page.
Figure 255. Cancel or retrigger a node instance in active stateIn the Process Variables panel of the Process Details page, you can add, update, or delete variables and save the changes to the process instance. For example, to add an object to a key, you can hover over the key and select the edit icon, provide an object in JSON format, and click the check mark icon or press Enter to apply the change. After making all changes to the process variables, click Save in the upper-right corner to save the changes or click the refresh icon to revert the changes.
Figure 256. Add a new property to process variablesFigure 257. Update a property in process variablesFigure 258. Save changes made to process variablesThe Jobs panel displays a list of available jobs related to the process instance and enables you to view details for each job.
Figure 259. Jobs panelFigure 260. Job detailsFor jobs in a Scheduled or an Error state, you can also select the Reschedule option to reschedule the jobs. You can modify the expiration time for one-time jobs, or the expiration time, repeat interval, and repeat limit for periodic jobs.
Figure 261. Reschedule a job in Scheduled or Error stateFigure 262. Define job reschedule detailsThe Milestones panel displays a list of available milestones for the process instance, if applicable.
Figure 263. Process instance milestonesThe Node Trigger panel displays a list of nodes that you can select from the drop-down menu and trigger.
Figure 264. Trigger a selected nodeAs a shortcut to view the process or application UI that triggered a process instance, you can select the Endpoint for the specified process instance.
Figure 265. Process instance endpoint -
Domain Explorer: Use this page to view data that is generated from your process instances in the available Kogito services, or domains, such as the
Travels
andVisaApplications
domains in this example. You can also refine which columns for the listed domain data are displayed based on available attributes, such as theapproved
,country
, ornationality
attributes in this example.Figure 266. Domain explorer with available domainsFigure 267. VisaApplications domain dataFigure 268. Attributes for refining VisaApplications domain data columnsFigure 269. Refined columns for VisaApplications domain dataFigure 270. Fields to filter VisaApplications domain dataFigure 271. Operators to filter VisaApplications domain dataFigure 272. Sample value to filter VisaApplications domain dataFigure 273. Filtered resultsFigure 274. Sorted results
-
10.11.2. Enabling Kogito Management Console security with OpenID Connect
For Quarkus-based Kogito services, you can use the Quarkus OpenID Connect adapter with the Kogito Management Console to enable the console to interact with the Kogito Data Index Service using bearer token authorization. These tokens are issued by OpenID Connect and OAuth 2.0 compliant authorization servers such as Keycloak.
| This procedure applies only when you are using a locally cloned copy of the Kogito Management Console repository in GitHub. |
-
You have cloned the Kogito Management Console repository from GitHub.
-
In a command terminal, navigate to the local clone of the Kogito Management Console repository and enter the following command to run the application with security enabled:
Run the Management Console with security enabledmvn clean compile quarkus:dev -Dquarkus.profile=keycloak
Ensure that the service is not started at the same port as the security server. You can change the port by adding -Dquarkus.http.port=PORT_NUMBER
to the start-up properties.The Kogito Management Console contains a Quarkus profile to encapsulate the security configuration, so if the service requires security, you can specify the
quarkus.profile=keycloak
property at build time to enable the needed security. If thekeycloak
Quarkus profile is not added, the OpenID Connect extension is disabled. -
Navigate to the
src/main/resources/application.properties
file of the Management Console project and add the following properties:Required security properties inapplications.properties
file# OpenID Connect configurations %keycloak.quarkus.oidc.enabled=true %keycloak.quarkus.oidc.tenant-enabled=true %keycloak.quarkus.oidc.auth-server-url=http://localhost:8280/auth/realms/kogito %keycloak.quarkus.oidc.client-id=kogito-console-quarkus %keycloak.quarkus.oidc.credentials.secret=secret %keycloak.quarkus.oidc.application-type=web-app %keycloak.quarkus.oidc.logout.path=/logout %keycloak.quarkus.oidc.logout.post-logout-path=/ # HTTP security configurations %keycloak.quarkus.http.auth.permission.authenticated.paths=/* %keycloak.quarkus.http.auth.permission.authenticated.policy=authenticated
The quarkus.oidc.enabled
property enables or disables security at build time, while thequarkus.oidc.tenant-enabled
property enables or disables security at runtime. -
Replace any property definitions with those of your specific environment, especially the following properties:
-
quarkus.oidc.auth-server-url
: The base URL of the OpenID Connect (OIDC) server, such ashttps://localhost:8280/auth
. All other OIDC server page and service URLs are derived from this URL. If you work with Keycloak OIDC server, ensure that the base URL is in the following format:https://HOST:PORT/auth/realms/KEYCLOAK_REALM
. -
quarkus.oidc.client-id
: The client ID of the application. Each application has a client ID that is used to identify the application. -
quarkus.oidc.credentials.secret
: The client secret for the application.
-
-
In the same
application.properties
file, also configure the resources to be exposed and the required permissions for accessing the resources.If you are enabling security at runtime using the quarkus.oidc.tenant-enabled
property, thequarkus.http.auth.permission
path and policy must specify how authentication is applied. By default, if security is enabled, the user must be authenticated to access any path. -
Stop and restart the Kogito Management Console to ensure that the security changes are applied.
10.12. Kogito Task Console
The Kogito Task Console is a user interface for viewing and interacting with user tasks in Kogito process services.
You can use the Task Console to view your list of assigned tasks, view the task details for each task, and move the task to the next phase of the task lifecycle. For more information about the task lifecycle, see Task lifecycle in Kogito processes.
The Task Console requires your Kogito services to use the Kogito Data Index Service. The Data Index Service enables the Task Console to access stored events related to tasks and domain data from your Kogito services. The Kogito Data Index Service requires Infinispan persistence and Apache Kafka messaging for your Kogito service. For more information about the Data Index Service, see Kogito Data Index Service.
10.12.1. Using the Kogito Task Console to interact with user tasks
You can use the Kogito Task Console to view and interact with user tasks in Kogito process services. You can run the Task Console for local Kogito services or add it to your Kogito infrastructure on OpenShift.
-
A Kogito Data Index Service instance is configured and running for your Kogito service. The Data Index Service enables the Task Console to access stored tasks and process data. The Data Index Service requires Infinispan persistence and Apache Kafka messaging for your Kogito service. For information about the Data Index Service, see Kogito Data Index Service.
-
The
application.properties
file of your Kogito project contains the following system properties for the location where the Kogito service is deployed, such ashttp://localhost:8080
, and for Quarkus Cross-Origin Resource Sharing (CORS) support.Application properties for REST URLskogito.service.url=http://HOST:PORT quarkus.http.cors=true
-
Go to the
task-console
artifacts page, select the latest release of the Kogito Task Console, and download thetask-console-VERSION-runner.jar
file to a local directory. -
In a command terminal, navigate to the directory location of the downloaded
task-console-VERSION-runner.jar
file and enter the following command to run the Task Console:Running the Task Console$ java -Dquarkus.http.port=8280 -jar task-console-VERSION-runner.jar
The default port for the Task Console is 8080, but this example specifies port 8280 to avoid conflicts with the example Kogito service running at port 8080.
Also, the Task Console uses the default Data Index Service port 8180. If you modified this port in your Data Index Service instance, you must also modify the port in the Task Console properties by using the start-up property
-Dkogito.dataindex.http.url=http://HOST:PORT
when you run the Task Console.To change the logging level of the Task Console, such as for debugging, you can specify the following start-up properties:
Modifying Task Console logging level for debugging$ java \ -Dquarkus.log.console.level=DEBUG -Dquarkus.log.category.\"org.kie.kogito\".min-level=DEBUG \ -Dquarkus.log.category.\"org.kie.kogito\".level=DEBUG \ -Dquarkus.http.port=8280 \ -jar task-console-VERSION-runner.jar
-
In a web browser, navigate to
http://localhost:8280
to open the Task Console. If you modified the configured Task Console port, use the modified location.Figure 276. Kogito Task ConsoleIn this example, the Task Console displays data for the
kogito-travel-agency
extended example application in thekogito-examples
repository in GitHub.The Task Inbox page lists the available user tasks that you can interact with. You can use the upper toolbar options to filter the tasks or use the column headers to sort the tasks as needed. You can also search for tasks by name or by partial name using wildcards, such as
Apply*
.Figure 277. Tasks assigned to the current userFigure 278. Available task status filtersFigure 279. Applied filters -
Select a task name to view task details and interact with the task:
Figure 280. Task detailsDepending on the current phase of the selected task, you can select from the available actions for that task, such as Abort, Release, Skip, or Complete, to move the task to the next phase.
For additional task details, you can select View details. This panel lists the task ID, state, owner, related process instance ID, and other helpful information about the task.
Figure 281. Task details panel
10.12.2. Enabling Kogito Task Console security with OpenID Connect
For Quarkus-based Kogito services, you can use the Quarkus OpenID Connect adapter with the Kogito Task Console to enable the console to interact with the Kogito Data Index Service using bearer token authorization. These tokens are issued by OpenID Connect and OAuth 2.0 compliant authorization servers such as Keycloak.
| This procedure applies only when you are using a locally cloned copy of the Kogito Task Console repository in GitHub. |
-
You have cloned the Kogito Task Console repository from GitHub.
-
In a command terminal, navigate to the local clone of the Kogito Task Console repository and enter the following command to run the application with security enabled:
Run the Task Console with security enabledmvn clean compile quarkus:dev -Dquarkus.profile=keycloak
Ensure that the service is not started at the same port as the security server. You can change the port by adding -Dquarkus.http.port=PORT_NUMBER
to the start-up properties.The Kogito Task Console contains a Quarkus profile to encapsulate the security configuration, so if the service requires security, you can specify the
quarkus.profile=keycloak
property at build time to enable the needed security. If thekeycloak
Quarkus profile is not added, the OpenID Connect extension is disabled. -
Navigate to the
src/main/resources/application.properties
file of the Task Console project and add the following properties:Required security properties inapplications.properties
file# OpenID Connect configurations %keycloak.quarkus.oidc.enabled=true %keycloak.quarkus.oidc.tenant-enabled=true %keycloak.quarkus.oidc.auth-server-url=http://localhost:8280/auth/realms/kogito %keycloak.quarkus.oidc.client-id=kogito-console-quarkus %keycloak.quarkus.oidc.credentials.secret=secret %keycloak.quarkus.oidc.application-type=web-app %keycloak.quarkus.oidc.logout.path=/logout %keycloak.quarkus.oidc.logout.post-logout-path=/ # HTTP security configurations %keycloak.quarkus.http.auth.permission.authenticated.paths=/* %keycloak.quarkus.http.auth.permission.authenticated.policy=authenticated
The quarkus.oidc.enabled
property enables or disables security at build time, while thequarkus.oidc.tenant-enabled
property enables or disables security at runtime. -
Replace any property definitions with those of your specific environment, especially the following properties:
-
quarkus.oidc.auth-server-url
: The base URL of the OpenID Connect (OIDC) server, such ashttps://localhost:8280/auth
. All other OIDC server page and service URLs are derived from this URL. If you work with Keycloak OIDC server, ensure that the base URL is in the following format:https://HOST:PORT/auth/realms/KEYCLOAK_REALM
. -
quarkus.oidc.client-id
: The client ID of the application. Each application has a client ID that is used to identify the application. -
quarkus.oidc.credentials.secret
: The client secret for the application.
-
-
In the same
application.properties
file, also configure the resources to be exposed and the required permissions for accessing the resources.If you are enabling security at runtime using the quarkus.oidc.tenant-enabled
property, thequarkus.http.auth.permission
path and policy must specify how authentication is applied. By default, if security is enabled, the user must be authenticated to access any path. -
Stop and restart the Kogito Task Console to ensure that the security changes are applied.
10.13. Kogito service execution
After you design your Kogito service, you can build and run your application and then send REST API requests to the application to execute your services. The exact REST API requests that you can use depend on how you set up the application.
For example, consider a Kogito service that is set up to generate a /persons
REST API endpoint and determines whether a specified customer is an adult or is underage. In this example, you can send the following POST
request using a REST client or curl utility to add an adult and execute the service:
{
"person": {
"name": "John Quark",
"age": 20
}
}
curl -X POST http://localhost:8080/persons -H 'content-type: application/json' -H 'accept: application/json' -d '{"person": {"name":"John Quark", "age": 20}}'
{
"id": "3af806dd-8819-4734-a934-728f4c819682",
"person": {
"name": "John Quark",
"age": 20,
"adult": false
},
"isAdult": true
}
For information about creating, running, and testing an example application with Kogito services, see Creating and running your first Kogito services.
For information about deploying your Kogito service to OpenShift, see Deploying Kogito services on OpenShift.
11. Orchestrating microservices with Serverless Workflow in Kogito
As a microservices developer or architect, you can use the Serverless Workflow specification to orchestrate application services in your Kogito project. The Serverless Workflow specification enables you to define declarative workflow models that orchestrate event-driven, serverless applications. The specification is hosted by the Cloud Native Computing Foundation (CNCF) and is currently a CNCF Sandbox project that is progressing to become an Incubating project.
For more information about Serverless Workflow, see the Serverless Workflow website.
11.1. Serverless Workflow orchestration
Serverless Workflow is a specification for defining declarative workflow models that orchestrate event-driven, serverless applications. The main benefit of a Serverless Workflow strategy is that it provides a clear separation of business logic and orchestration logic in your serverless applications. Developers can focus on solving business logic inside functions and use workflows to define function invocations, specify event behavior, and provide data management for different microservices.
The Serverless Workflow specification defines a vendor-neutral, platform-independent, and declarative workflow model that you can use across multiple cloud or container platforms. This portability enables you to move your workflow definitions from one cloud or container platform to another with the same execution results.
The specification is hosted by the Cloud Native Computing Foundation (CNCF) and is currently a CNCF Sandbox project that is progressing to become an Incubating project. The specification has been created by CNCF community members and individuals from different companies and is a fully open source project (Apache 2.0 license).
The target users of Serverless Workflow orchestration are mostly developers and architects who want to define logical steps of execution declaratively (no code) for cloud-native services. Although you can orchestrate your services using process diagrams in Business Process Model and Notation (BPMN), the Serverless Workflow has less focus on business definition and more focus on function-level steps of execution. Serverless Workflow is also designed specifically for microservice orchestration and therefore has a smaller scope than BPMN. Serverless Workflow also enables you to write workflows in formats (JSON or YAML) that might be better suited for developing and deploying serverless applications in cloud or container environments.
Ultimately, the choice of which specification to use for orchestrating event-driven microservices depends on your environment needs, development goals, and personal preference.
11.1.1. Serverless Workflow architecture
The Serverless Workflow specification provides a JSON schema that defines the structure of JSON or YAML workflow definitions. The specification also provides a set of SDKs for Java and Go that can help developers get started with the specification to create workflows. The specification provides a set of workflow extensions, such as key performance indicators (KPIs), that you can use to enhance workflow definitions with additional information. This information can then be used during execution of the workflows to provide additional data, such as metrics for improving workflow performance.
The following diagram illustrates a general Serverless Workflow architecture:
Serverless Workflow focuses on orchestration of event-driven microservices. Although the specification provides a generic markup that you can use for general workflow or pipeline (CI/CD) definitions, its declarative nature is designed for microservice orchestration.
Similar to other specification-based standards for business automation, Serverless Workflow provides a unified core definition for workflows. For example, the following diagram illustrates a single Serverless Workflow definition that is executed on multiple runtime services. Each of these services can then be deployed onto various cloud or container platforms with the same execution results.
11.1.2. Serverless Workflow definitions
In the Serverless Workflow specification, Serverless Workflow definitions are JSON or YAML files with the extension .sw.json
or .sw.yaml
that provide the orchestration details for the relevant application services.
A Serverless Workflow definition file consists of the following basic components:
{
"id": "sampleWorkflow",
"version": "1.0",
"name": "Sample Workflow",
"description": "Sample Workflow",
"functions": [],
"events": [],
"states": []
}
id: sampleWorkflow
version: '1.0'
name: Sample Workflow
description: Sample Workflow
functions: []
events: []
states: []
The Serverless Workflow functions
, events
, and states
are the core constructs for defining the orchestration behavior for your services. You can use one or all of these three constructs in your workflow definitions.
-
functions
: Function definitions are reusable constructs that you can use to define invocation information about services that need to be invoked during workflow execution. Function definitions can be referenced by workflowstates
(control-logic blocks) whenever a service needs to be invoked. -
events
: Event definitions are reusable constructs that you can use to define all consumed and produced events during workflow execution. Serverless Workflow requires CloudEvents format for both consumed and produced events. Event definitions can be referenced by workflow states to determine how a workflow instance is created, what events are needed to continue workflow execution, what events need to be produced during workflow execution, and how multiple events are associated with one another (correlation rules). You can also use event definitions to trigger function or service invocation for services that do not use exposed invocation endpoints and that are only invoked by events. -
states
: State definitions enable you to define your workflow states (control-logic blocks) and determine what your workflow should do. State definitions specify details such as how the workflow is started, what data is expected, how the workflow should transition from one state to another given some data or event constraints, and how and when the workflow execution completes.The following diagram illustrates some of the control-flow constructs that you can build with Serverless Workflow state definitions:
Figure 284. Example control-flow constructs from state definitionsFor more information about supported workflow states, see the Serverless Workflow specification.
For example, the following Serverless Workflow definition performs a customer credit check in a loan application service. In this example, the Serverless Workflow integrates with an external microservice to assess customer credit and approve or deny the customer loan application. After this decision is made, the service emits a CloudEvents message that includes the decision information as part of the payload. The workflow receives this callback event and triggers workflow transitions based on the credit check decision results.
{
"id": "customercreditcheck",
"version": "1.0",
"name": "Customer Credit Check Workflow",
"description": "Perform Customer Credit Check",
"functions": [
{
"name": "callCreditCheckMicroservice",
"resource": "creditCheckResource",
"type": "service"
},
{
"name": "sendRejectionEmailFunction",
"resource": "rejectEmailResource"
}
],
"events": [
{
"name": "CreditCheckCompletedEvent",
"type": "creditCheckCompleteType",
"source": "creditCheckSource",
"correlation": [
{
"contextAttributeName": "customerId"
}
]
}
],
"states": [
{
"name": "CheckCredit",
"type": "callback",
"start": {
"kind": "default"
},
"action": {
"functionRef": {
"refName": "callCreditCheckMicroservice",
"parameters": {
"customer": "{{ $.customer }}"
}
}
},
"eventRef": "CreditCheckCompletedEvent",
"timeout": "PT15M",
"transition": {
"nextState": "EvaluateDecision"
}
},
{
"name": "EvaluateDecision",
"type": "switch",
"dataConditions": [
{
"condition": "{{<EMAIL_ADDRESS>== 'Approved')] }}",
"transition": {
"nextState": "StartApplication"
}
},
{
"condition": "{{<EMAIL_ADDRESS>== 'Denied')] }}",
"transition": {
"nextState": "RejectApplication"
}
}
],
"default": {
"transition": {
"nextState": "RejectApplication"
}
}
},
{
"name": "StartApplication",
"type": "subflow",
"workflowId": "startApplicationWorkflowId",
"end": {
"kind": "default"
}
},
{
"name": "RejectApplication",
"type": "operation",
"actionMode": "sequential",
"actions": [
{
"functionRef": {
"refName": "sendRejectionEmailFunction",
"parameters": {
"applicant": "{{ $.customer }}"
}
}
}
],
"end": {
"kind": "default"
}
}
]
}
id: customercreditcheck
version: '1.0'
name: Customer Credit Check Workflow
description: Perform Customer Credit Check
functions:
- name: callCreditCheckMicroservice
resource: creditCheckResource
type: microservice
- name: sendRejectionEmailFunction
resource: rejectEmailResource
events:
- name: CreditCheckCompletedEvent
type: creditCheckCompleteType
source: creditCheckSource
correlation:
- contextAttributeName: customerId
states:
- name: CheckCredit
type: callback
start:
kind: default
action:
functionRef:
refName: callCreditCheckMicroservice
parameters:
customer: "{{ $.customer }}"
eventRef: CreditCheckCompletedEvent
timeout: PT15M
transition:
nextState: EvaluateDecision
- name: EvaluateDecision
type: switch
dataConditions:
- condition: "{{<EMAIL_ADDRESS>== 'Approved')] }}"
transition:
nextState: StartApplication
- condition: "{{<EMAIL_ADDRESS>== 'Denied')] }}"
transition:
nextState: RejectApplication
default:
transition:
nextState: RejectApplication
- name: StartApplication
type: subflow
workflowId: startApplicationWorkflowId
end:
kind: default
- name: RejectApplication
type: operation
actionMode: sequential
actions:
- functionRef:
refName: sendRejectionEmailFunction
parameters:
applicant: "{{ $.customer }}"
end:
kind: default
In this example, the workflow uses the following data input:
{
"customer": {
"id": "customer123",
"name": "John Doe",
"SSN": 123456,
"yearlyIncome": 50000,
"address": "123 MyLane, MyCity, MyCountry",
"employer": "MyCompany"
}
}
The example workflow receives the following callback events:
{
"specversion" : "1.0",
"type" : "creditCheckCompleteType",
"datacontenttype" : "application/json",
...
"data": {
"creditCheck": [
{
"id": "customer123",
"score": 700,
"decision": "Approved",
"reason": "Good credit score"
}
]
}
}
{
"specversion" : "1.0",
"type" : "creditCheckCompleteType",
"datacontenttype" : "application/json",
...
"data": {
"creditCheck": [
{
"id": "customer123",
"score": 580,
"decision": "Denied",
"reason": "Low credit score. Recent late payments"
}
]
}
}
For more Serverless Workflow definition examples, see the Serverless Workflow specification.
11.1.3. Serverless Workflow use cases
Use cases for the Serverless Workflow specification vary widely and depend on the reference implementations and the ecosystem available during workflow execution, such as available functions, services, and events.
The following scenarios illustrate example use cases for Serverless Workflow orchestration with microservices. For more Serverless Workflow use cases, see the Serverless Workflow specification.
- Payment processing
-
Servlerless Workflow is ideal for coordinating session-based applications, such as e-commerce sites. You can use Serverless Workflow to coordinate all steps of the checkout process, and even enable users to take a photo of their credit card instead of having to type in the numbers and information.
Figure 285. Serverless Workflow orchestration for payment processing - Online vehicle auction
-
You can use Serverless Workflow to coordinate all steps of an online vehicle auction, such as the following aspects of the orchestration:
-
Authentication of users making bids
-
Communication with bidding and inventory services
-
Decisions to start and end the auction under certain conditions
Figure 286. Serverless Workflow orchestration for online vehicle auction -
- Data analysis
-
You can use Serverless Workflow to coordinate data analysis, such as for marketing and sales information. Analysis can be scheduled on a timely basis to trigger workflow coordination of different extract, transform, load (ETL) services.
Figure 287. Serverless Workflow orchestration for data analysis - Error notifications
-
You can design Serverless Workflow definitions that trigger notifications about the success or failure of the workflow orchestration. In conjunction with available messaging services, you can notify developers on different platforms of any failures, including error information and the exact point in the execution where the failure occurred. You can also log the workflow execution status to cloud storage services for further analysis.
Figure 288. Serverless Workflow orchestration for error notifications - Continuous integration and continuous deployment (CI/CD)
-
Serverless Workflow can help you build efficient continuous integration and continuous deployment (CI/CD) solutions. Code check-ins can trigger website builds and automatic redeploys. Pull requests can trigger automated tests that ensure the code is well-tested before human reviews.
Figure 289. Serverless Workflow orchestration for CI/CD
11.2. Serverless Workflow orchestration in Kogito
Kogito provides the runtime implementation that supports Serverless Workflow, including both JSON and YAML formats, in compliance with the Serverless Workflow specification.
You can use Serverless Workflow definition files in your Kogito project to define your domain-specific orchestration services. Your Serverless Workflow files can be in JSON or YAML format with the extension .sw.json
or .sw.yaml
.
The following diagram illustrates Serverless Workflow orchestration in Kogito:
11.2.1. Serverless Workflow example in Kogito
The following example is a real-world Serverless Workflow scenario in Kogito that demonstrates how you can use Serverless Workflow definitions to orchestrate your Kogito services. In this scenario, an order service uses Serverless Workflow to process orders from multiple sources and approve or deny orders.
This example is based on the orders-demo application in the Serverless-Workflow-Kogito repository in GitHub. However, this example may differ from the exact example source code as Kogito continues to be developed. For more example Kogito services that use Serverless Workflow, see the kogito-examples repository in GitHub.
|
The following diagram illustrates the basic architecture of this scenario:
New orders can come from different sources, such as web applications or messaging services. Each order is then converted into CloudEvents messages, which represent the events that need to trigger the workflow execution. The events are pushed to an Apache Kafka topic.
New order events that are pushed to Kafka trigger new instances of the workflow. The workflow invokes a business rule service and a human task service to make the order approval decision. The business rule service can be a Kogito service with Decision Model and Notation (DMN) decision models or Drools Rule Language (DRL) rules, or it can be an external service. For this example, the rule service uses a DRL rules in Kogito to verify whether the order can be auto-approved. If the order cannot be auto-approved, then the workflow uses the human task service, which likewise can be a Kogito service or an external service, to notify a manager that the order requires human approval.
After the order decision is made, the workflow generates an event in CloudEvents format that notifies other services or other workflows that a decision was made for a particular order.
To orchestrate these services in this way, the example uses the following ordersworkflow.sw.json
Serverless Workflow definition:
ordersworkflow.sw.json
workflow definition (JSON){
"id": "ordersworkflow",
"name": "Orders Workflow",
"version": "1.0",
"events": [
{
"name": "NewOrderEvent",
"source": "neworder",
"type": "kafka"
},
{
"name": "ApprovalDecisionEvent",
"source": "out-approvaldecision",
"type": "kafka"
}
],
"functions": [
{
"name": "AutoAproveOrderFunction",
"type": "rule",
"metadata": {
"ruleflowgroup": "neworder"
}
},
{
"name": "OrderManagerApprovalFunction",
"type": "decision",
"metadata": {
"taskname": "managerApproval",
"actorid": "managers",
"groupid": "managers"
}
}
],
"states": [
{
"name": "HandleNewOrder",
"type": "event",
"start": {
"kind": "default"
},
"eventsActions": [
{
"eventRefs": [
"NewOrderEvent"
],
"actions": [
{
"functionRef": {
"refName": "AutoAproveOrderFunction"
}
}
]
}
],
"transition": {
"nextState": "CheckIfNeedManagerApproval"
}
},
{
"name": "CheckIfNeedManagerApproval",
"type": "switch",
"dataConditions": [
{
"path": "$.decision",
"value": "Approved",
"operator": "equals",
"transition": {
"nextState": "OrderAutoApproved"
}
},
{
"path": "$.decision",
"value": "NeedManagerApproval",
"operator": "equals",
"transition": {
"nextState": "OrderManagerApproval"
}
}
],
"default": {
"nextState": "OrderManagerApproval"
}
},
{
"name": "OrderAutoApproved",
"type": "inject",
"data": {
"finalDecision": "Approved"
},
"end": {
"kind": "event",
"produceEvent": {
"eventRef": "ApprovalDecisionEvent"
}
}
},
{
"name": "OrderManagerApproval",
"type": "operation",
"actionMode": "sequential",
"actions": [
{
"name": "managerAprovalAction",
"functionRef": {
"refName": "OrderManagerApprovalFunction"
}
}
],
"end": {
"kind": "event",
"produceEvent": {
"eventRef": "ApprovalDecisionEvent"
}
}
}
]
}
The following diagram illustrates the basic structure and sequence of this example workflow definition:
ordersworkflow.sw.json
workflow definitionThe HandleNewOrder
state is the workflow starting state. This state is an event
type state that requires one or more events to be consumed before the workflow can be invoked. This event state defines the instances of this workflow that are created when the referenced NewOrderEvent
is consumed. In this case, events are consumed by Kafka.
After the NewOrderEvent
is consumed, the state defines a list of actions
to be performed. Actions define all the functions or services that must be invoked as part of the workflow. In this case, a single AutoApproveOrderFunction
function or service defines how to invoke the rule service.
After the execution of the rule service is complete, the event state specifies that the workflow must transition to the CheckIfNeedManagerApprvoal
state, which is a switch
type state. The order is then either auto-approved if no manager approval is required, or is assigned to a manager to complete the remaining states of the workflow.
For more example Kogito services that use Serverless Workflow, see the following example applications in GitHub:
-
serverless-workflow-events-quarkus
: A Serverless Workflow service for processing job applicant approvals and that showcases event-driven services -
serverless-workflow-greeting-quarkus
andserverless-workflow-greeting-springboot
: A Serverless Workflow greeting service with both JSON and YAML workflow definitions -
serverless-workflow-service-calls-quarkus
andserverless-workflow-service-calls-springboot
: A Serverless Workflow service for returning country information
11.3. Creating and editing Serverless Workflow definitions in Kogito
You can use Serverless Workflow definition files in your Kogito project to define your domain-specific orchestration services. Your Serverless Workflow definition files can be in JSON or YAML format with the extension .sw.json
or .sw.yaml
.
-
You have created a Kogito project and have included any Java objects or other business assets required for your Serverless Workflow service. For information about creating a project, see Creating and running your first Kogito services.
-
In your Kogito project, create or import a
.sw.json
or.sw.yaml
Serverless Workflow definition file in the relevant folder, typically insrc/main/resources
.Kogito supports both JSON and YAML formats for workflow definitions. You can use multiple workflow definitions in both formats if needed.
-
Open the workflow definition file and define the following basic components:
Serverless Workflow definition format in JSON{ "id": "sampleWorkflow", "version": "1.0", "name": "Sample Workflow", "description": "Sample Workflow", "functions": [], "events": [], "states": [] }
Serverless Workflow definition format in YAMLid: sampleWorkflow version: '1.0' name: Sample Workflow description: Sample Workflow functions: [] events: [] states: []
The Serverless Workflow
functions
,events
, andstates
are the core constructs for defining the orchestration behavior for your services. You can use one or all of these three constructs in your workflow definitions.-
functions
: Function definitions are reusable constructs that you can use to define invocation information about services that need to be invoked during workflow execution. Function definitions can be referenced by workflowstates
(control-logic blocks) whenever a service needs to be invoked. -
events
: Event definitions are reusable constructs that you can use to define all consumed and produced events during workflow execution. Serverless Workflow requires CloudEvents format for both consumed and produced events. Event definitions can be referenced by workflow states to determine how a workflow instance is created, what events are needed to continue workflow execution, what events need to be produced during workflow execution, and how multiple events are associated with one another (correlation rules). You can also use event definitions to trigger function or service invocation for services that do not use exposed invocation endpoints and that are only invoked by events. -
states
: State definitions enable you to define your workflow states (control-logic blocks) and determine what your workflow should do. State definitions specify details such as how the workflow is started, what data is expected, how the workflow should transition from one state to another given some data or event constraints, and how and when the workflow execution completes.
For example, the following Serverless Workflow definition performs a customer credit check in a loan application service to approve or deny the customer loan application:
Example Serverless Workflow definition for credit check (JSON){ "id": "customercreditcheck", "version": "1.0", "name": "Customer Credit Check Workflow", "description": "Perform Customer Credit Check", "functions": [ { "name": "callCreditCheckMicroservice", "resource": "creditCheckResource", "type": "service" }, { "name": "sendRejectionEmailFunction", "resource": "rejectEmailResource" } ], "events": [ { "name": "CreditCheckCompletedEvent", "type": "creditCheckCompleteType", "source": "creditCheckSource", "correlation": [ { "contextAttributeName": "customerId" } ] } ], "states": [ { "name": "CheckCredit", "type": "callback", "start": { "kind": "default" }, "action": { "functionRef": { "refName": "callCreditCheckMicroservice", "parameters": { "customer": "{{ $.customer }}" } } }, "eventRef": "CreditCheckCompletedEvent", "timeout": "PT15M", "transition": { "nextState": "EvaluateDecision" } }, { "name": "EvaluateDecision", "type": "switch", "dataConditions": [ { "condition": "{{<EMAIL_ADDRESS>== 'Approved')] }}", "transition": { "nextState": "StartApplication" } }, { "condition": "{{<EMAIL_ADDRESS>== 'Denied')] }}", "transition": { "nextState": "RejectApplication" } } ], "default": { "transition": { "nextState": "RejectApplication" } } }, { "name": "StartApplication", "type": "subflow", "workflowId": "startApplicationWorkflowId", "end": { "kind": "default" } }, { "name": "RejectApplication", "type": "operation", "actionMode": "sequential", "actions": [ { "functionRef": { "refName": "sendRejectionEmailFunction", "parameters": { "applicant": "{{ $.customer }}" } } } ], "end": { "kind": "default" } } ] }
Example Serverless Workflow definition for credit check (YAML)id: customercreditcheck version: '1.0' name: Customer Credit Check Workflow description: Perform Customer Credit Check functions: - name: callCreditCheckMicroservice resource: creditCheckResource type: microservice - name: sendRejectionEmailFunction resource: rejectEmailResource events: - name: CreditCheckCompletedEvent type: creditCheckCompleteType source: creditCheckSource correlation: - contextAttributeName: customerId states: - name: CheckCredit type: callback start: kind: default action: functionRef: refName: callCreditCheckMicroservice parameters: customer: "{{ $.customer }}" eventRef: CreditCheckCompletedEvent timeout: PT15M transition: nextState: EvaluateDecision - name: EvaluateDecision type: switch dataConditions: - condition: "{{<EMAIL_ADDRESS>== 'Approved')] }}" transition: nextState: StartApplication - condition: "{{<EMAIL_ADDRESS>== 'Denied')] }}" transition: nextState: RejectApplication default: transition: nextState: RejectApplication - name: StartApplication type: subflow workflowId: startApplicationWorkflowId end: kind: default - name: RejectApplication type: operation actionMode: sequential actions: - functionRef: refName: sendRejectionEmailFunction parameters: applicant: "{{ $.customer }}" end: kind: default
For more Serverless Workflow definition examples in Kogito, see Serverless Workflow orchestration in Kogito.
-
-
Continue adding and defining any remaining components for your workflow definition files and save the completed files.
After you define your serverless workflow definitions, you can build and deploy your Kogito services as usual to your preferred cloud or container platform, such as OpenShift. When an event trigger occurs, your application orchestrates your Kogito services according to the workflow definition or definitions that you have defined. If you are using a serverless deployment platform, such as OpenShift Serverless, your application automatically scales up based on incoming demand, or scales to zero after use.
12. Configuring Kogito supporting services and runtime capabilities
As a developer of business processes and decisions, you can configure Kogito supporting services and runtime properties for advanced use cases with your Kogito services.
12.1. Kogito supporting services and runtime configuration
Kogito supporting services consist of middleware infrastructure services and other dedicated services that help you build additional functionality in the Kogito domain-specific services that you develop.
Kogito supports the following key middleware infrastructure services:
-
Infinispan persistence
-
Apache Kafka reactive messaging
Kogito also provides the following dedicated services:
-
Kogito Data Index Service indexing and querying
-
Kogito Jobs Service job scheduling
The Kogito runtime supports various configuration options for these supporting services and for other capabilities, such as the following examples:
-
Custom event listeners
-
Prometheus metrics monitoring
-
Process instance management
These supporting services, runtime configurations, and Kogito add-on components enable you to optimize your Kogito domain-specific services for your business automation requirements.
12.2. Kogito runtime properties quick reference
The following table serves as a quick reference for commonly used runtime configuration properties supported by Kogito. You can define these properties in the src/main/resources/application.properties
file of the relevant Kogito project or by using the -D
prefix during application start-up.
| Some of these properties might require accompanying dependencies in the relevant Kogito project to enable the specified capability. For more information about dependency requirements, review the sections of the Kogito configuration documentation that relate to that property. |
| Relevance | Property | Description |
|---|---|---|
Events |
|
Determines whether runtime events are published for process instances, either Default value: Example: |
|
Determines whether runtime events are published for user task instances, either Default value: Example: |
|
|
Determines whether messages (sent or received through message events) are published in CloudEvents format, either Example: |
|
Infinispan persistence |
For Spring Boot: |
Defines the location where an Infinispan Server is running, typically used to connect your application to Infinispan for persistence Example: For Spring Boot: |
|
Identifies the Infinispan user name and password to authenticate Infinispan persistence capabilities in the relevant application, if required, such as in the Kogito Data Index Service Examples:
|
|
|
Defines an optional template name of the Infinispan cache configuration to be used to persist process instance data Example: |
|
Kafka messaging |
Incoming:
Outgoing:
For Spring Boot: |
Defines the connector, topic, and deserializer for the incoming and outgoing messages and channels for reactive messaging with Apache Kafka Examples for incoming:
Examples for outgoing:
For Spring Boot: |
Kogito Jobs Service |
|
Defines the location where the Kogito service is deployed, typically used by the Jobs Service to find the source of the jobs Example: |
|
Defines the callback URL that posts to a running Kogito Jobs Service Example: |
|
|
(Specified in Jobs Service) Identifies the persistence mechanism used by the Jobs Service, either Default value: Example: |
|
|
(Specified in Jobs Service) Defines the retry back-off time in milliseconds between job execution attempts, in case the execution fails Default value: Example: |
|
|
(Specified in Jobs Service) Defines the maximum interval in milliseconds when retrying to execute jobs, in case the execution fails Default value: Example: |
|
|
(Specified in Jobs Service) Identifies the Kafka bootstrap server address with the port used to publish events Default value: Example: |
|
|
(Specified in Jobs Service) Defines the name of the Kafka topic where the events are published Default value: Example: |
|
RESTEasy |
|
(Spring Boot only) Lists comma-separated package names that contain REST endpoint Java classes. Sub-packages are automatically scanned. Wildcard notation is supported. Packages generated by DMN namespaces typically start with Example: |
12.3. Kogito runtime events
A runtime event is record of a significant change of state in the application domain at a point in time. Kogito emits runtime events as a result of successfully executed requests, or units of work, in a process instance or task instance in a process. Kogito can use these events to notify third parties about changes to the BPMN process instance and its data.
12.3.1. Process instance events
For every executed process instance, an event is generated that contains information for that instance, such as the following information:
-
Process instance metadata, such as the process definition ID, process instance ID, process instance state, and other identifying information
-
Node instances that have been triggered during the execution
-
Variables used and the current state of variables after the execution
These events provide a complete view of the process instances being executed and can be consumed by an event listener, such as a ProcessEventListener
configuration.
If multiple processes are executed within a single request (unit of work), each process instance is given a dedicated event.
The following event is an example process instance event generated after the request was executed successfully:
{
"specversion": "0.3",
"id": "f52af50c-4fe2-4581-9184-7ad48137fb3f",
"source": null,
"type": "ProcessInstanceEvent",
"time": "2019-08-05T17:47:49.019494+02:00[Europe/Warsaw]",
"data": {
"id": "c1aced49-399b-4938-9071-b2ffa3fb7045",
"parentInstanceId": null,
"rootInstanceId": null,
"processId": "deals",
"processName": "SubmitDeal",
"startDate":<PHONE_NUMBER>015,
"endDate": null,
"state": 1,
"nodeInstances": [
{
"id": "a8fe24c4-27a5-4869-85df-16e9f170f2c4",
"nodeId": "2",
"nodeDefinitionId": "CallActivity_1",
"nodeName": "Call a deal",
"nodeType": "SubProcessNode",
"triggerTime":<PHONE_NUMBER>015,
"leaveTime": null
},
{
"id": "7a3bf1b1-b167-4928-969d-20bddf16c87a",
"nodeId": "1",
"nodeDefinitionId": "StartEvent_1",
"nodeName": "StartProcess",
"nodeType": "StartNode",
"triggerTime":<PHONE_NUMBER>015,
"leaveTime":<PHONE_NUMBER>015
}
],
"variables": {
"name": "my fancy deal",
"traveller": {
"firstName": "John",
"lastName": "Doe",
"email"<EMAIL_ADDRESS>"nationality": "American",
"address": {
"street": "main street",
"city": "Boston",
"zipCode": "10005",
"country": "US"
}
}
}
},
"kogitoProcessinstanceId": "c1aced49-399b-4938-9071-b2ffa3fb7045",
"kogitoParentProcessinstanceId": null,
"kogitoRootProcessinstanceId": null,
"kogitoProcessId": "deals",
"kogitoProcessinstanceState": "1"
}
The event is in CloudEvents format so that it can be consumed efficiently by other entities.
The event data also includes the following extensions to enable event routing based on the event metadata without requiring the body of the event:
-
kogitoProcessinstanceId
-
kogitoParentProcessinstanceId
-
kogitoRootProcessinstanceId
-
kogitoProcessId
-
kogitoProcessinstanceState
12.3.2. User task instance events
If an executed request (unit of work) in a process instance interacts with a user task, an event is generated for that user task and contains information for the task instance, such as the following information:
-
Task metadata, such as the task description, priority, start and complete dates, and other identifying information
-
Task input and output data
-
Task assignments, such as the task owner, potential users and groups, business administrator and business administrator groups, or excluded users
-
Task reference name that should be used to interact with the task using the Kogito service endpoints
The following event is an example user task instance event generated after the relevant request was executed successfully:
{
"data": {
"adminGroups": [],
"adminUsers": [],
"excludedUsers": [],
"id": "4d899471-19dd-485d-b7f4-b313185d430d",
"inputs": {
"Locale": "en-UK",
"trip": {
"begin": "2019-09-22T22:00:00Z[UTC]",
"city": "Boston",
"country": "US",
"end": "2019-09-26T22:00:00Z[UTC]",
"visaRequired": true
},
"TaskName": "VisaApplication",
"NodeName": "Apply for visa",
"Priority": "1",
"Skippable": "true",
"traveller": {
"address": {
"city": "Krakow",
"country": "Poland",
"street": "Polna",
"zipCode": "12345"
},
"email"<EMAIL_ADDRESS>"firstName": "Jan",
"lastName": "Kowalski",
"nationality": "Polish"
}
},
"outputs": {},
"potentialGroups": [],
"potentialUsers": [],
"processId": "travels",
"processInstanceId": "63c297cb-f5ac-4e20-8254-02f37bd72b80",
"referenceName": "VisaApplication",
"startDate": "2019-09-16T15:22:26.658Z[UTC]",
"state": "Ready",
"taskName": "Apply for visa",
"taskPriority": "1"
},
"id": "9c340cfa-c9b6-46f2-a048-e1114b077a7f",
"kogitoProcessId": "travels",
"kogitoProcessinstanceId": "63c297cb-f5ac-4e20-8254-02f37bd72b80",
"kogitoUserTaskinstanceId": "4d899471-19dd-485d-b7f4-b313185d430d",
"kogitoUserTaskinstanceState": "Ready",
"source": "http://localhost:8080/travels",
"specversion": "0.3",
"time": "2019-09-16T17:22:26.662592+02:00[Europe/Berlin]",
"type": "UserTaskInstanceEvent"
}
The event data also includes the following extensions to enable event routing based on the event metadata without requiring the body of the event:
-
kogitoUserTaskinstanceId
-
kogitoUserTaskinstanceState
-
kogitoProcessinstanceId
-
kogitoProcessId
12.3.3. Event publishing
Kogito generates events only when at least one publisher is configured. A Kogito service environment can have many event publishers that publish these events into different channels.
By default, Kogito includes the following message-based event publishers, depending on your application framework:
-
For Quarkus: Reactive Messaging for sending events using Apache Kafka, Apache Camel, Advanced Message Queuing Protocol (AMQP), or MQ Telemetry Transport (MQTT)
-
For Spring Boot: Spring for Apache Kafka for sending events using Kafka
To enable or disable event publishing, you can adjust the following properties in the src/main/resources/application.properties
file in your Kogito project:
-
kogito.events.processinstances.enabled
: Enables or disables publishing for process instance events (default:enabled
) -
kogito.events.usertasks.enabled
: Enables or disables publishing for user task instance events (default:enabled
)
To develop additional event publishers, you can implement the org.kie.kogito.event.EventPublisher
implementation and include the required annotations for JavaBeans discovery.
12.3.4. Enabling Kafka messaging for Kogito services
Kogito supports the MicroProfile Reactive Messaging specification for messaging in your services. You can enable messaging to configure message events as either input or output of business process execution.
For example, the following handle-travelers.bpmn2
process uses messaging start and end events to communicate with travelers:
In this example, the message start and end events require the following information:
-
Message name that maps to the channel that delivers messages
-
Message payload that maps to a process instance variable
For this procedure, the messaging is based on Apache Kafka as the event publisher, so you must have Kafka installed in order to enable messaging. Your marshalling configuration depends on the messaging solution that you use.
-
Apache Kafka is installed and includes any required topics. For information about Kafka installation and configuration, see the Apache Kafka documentation.
-
Add the following dependencies to the
pom.xml
file of your Kogito project:On Quarkus<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-smallrye-reactive-messaging-kafka</artifactId> </dependency>
On Spring Boot<dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency>
-
Configure the incoming and outgoing messaging channels and properties:
-
On Quarkus: Add the following properties to the
src/main/resources/application.properties
file in your Kogito project to configure the incoming and outgoing messages and channels:Configure incoming and outgoing messages and channelsmp.messaging.incoming.travellers.connector=smallrye-kafka mp.messaging.incoming.travellers.topic=travellers mp.messaging.incoming.travellers.value.deserializer=org.apache.kafka.common.serialization.StringDeserializer mp.messaging.outgoing.processedtravellers.connector=smallrye-kafka mp.messaging.outgoing.processedtravellers.topic=processedtravellers mp.messaging.outgoing.processedtravellers.value.serializer=org.apache.kafka.common.serialization.StringSerializer
Replace
travellers
with the name of the message start event. Replaceprocessedtravellers
with the name of the message end event.To prevent execution errors due to long wait times with messaging, you can also use the following property to disable waiting for message completion:
Disable message wait timemp.messaging.outgoing.[channel-name].waitForWriteCompletion=false
-
On Spring Boot: Add the following property to the
src/main/resources/application.properties
file in your Kogito project to configure the messaging channel, and create the JavaBeans for the incoming and outgoing messages:Configure messaging channelkafka.bootstrapAddress=localhost:9092
Create JavaBeans for incoming messages@EnableKafka @Configuration public class KafkaConsumerConfig { @Value(value = "${kafka.bootstrapAddress}") private String bootstrapAddress; public ConsumerFactory<String, String> consumerFactory() { Map<String, Object> props = new HashMap<>(); props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress); props.put(ConsumerConfig.GROUP_ID_CONFIG, "travellers-group"); return new DefaultKafkaConsumerFactory<>(props, new StringDeserializer(), new StringDeserializer()); } @Bean public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() { ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>(); factory.setConsumerFactory(consumerFactory()); return factory; } }
Create JavaBeans for outgoing messages@Configuration public class KafkaProducerConfig { @Value(value = "${kafka.bootstrapAddress}") private String bootstrapAddress; @Bean public ProducerFactory<String, String> producerFactory() { Map<String, Object> configProps = new HashMap<>(); configProps.put(JsonSerializer.ADD_TYPE_INFO_HEADERS, false); configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress); configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); return new DefaultKafkaProducerFactory<>(configProps); } @Bean public KafkaTemplate<String, String> kafkaTemplate() { return new KafkaTemplate<>(producerFactory()); } }
-
| As an alternative to enabling Kafka messaging explicitly in Kogito services, you can use the Kogito Operator to install the Kafka infrastructure and enable messaging for the service during deployment on OpenShift. For more information about enabling Kafka messaging with the Kogito Operator, see Kogito Operator interaction with Apache Kafka. |
For example Kogito services with Kafka messaging, see the following example applications in GitHub:
-
process-kafka-quickstart-quarkus
: Example on Quarkus -
process-kafka-quickstart-springboot
: Example on Spring Boot
12.3.5. Registering event listeners