-
Notifications
You must be signed in to change notification settings - Fork 213
Configuration
IMPORTANT: This Kogito wiki is deprecated. For the latest Kogito documentation, see the Kogito documentation page. To contribute to Kogito documentation, see the
master-kogito
branch of thekie-docs
repository in GitHub.
There are several configuration that can be needed when implementing Kogito enabled applications. Some (but not all) are
-
registering work item handlers
-
registering event listeners
-
enabling metrics
-
enabling persistence
-
enabling events produced by runtimes
-
use Kogito Job Service as timer service
These various items might require dependencies setup, code and configuration in the application.properties file.
To be able to use custom service tasks a work item handler must be registered. Once the work item handler is implemented to can be either packaged in the application itself or as dependency of the application.
WorkItemHandlerConfig
class should be created to provide custom work item handlers. It must implement org.kie.kogito.process.WorkItemHandlerConfig
although recommended is to always extend the default implementation (org.kie.kogito.process.impl.DefaultWorkItemHandlerConfig
) to benefit from the out of the box provided handlers as well.
@ApplicationScoped
public class CustomWorkItemHandlerConfig extends DefaultWorkItemHandlerConfig {{
register("MyServiceTask", new MyServiceWorkItemHandler());
}}
Note
|
These classes are meant to be injectable so ensure you properly annotate the class (@ApplicationScoped /@Component ) so they can be found and registered.
|
You can also take advantage of life cycle method like @PostConstruct
and @PreDestroy
to manage your handlers.
Event listeners are registered in similar way as work item handlers. Though these are separated into rule or process related event listeners and as such are implementing different interfaces.
-
org.kie.kogito.process.ProcessEventListenerConfig
-
org.kie.kogito.rules.RuleEventListenerConfig
same as with work item handlers it’s recommended to always extend the default implementation of the config class
-
org.kie.kogito.process.impl.DefaultProcessEventListenerConfig
-
org.drools.core.config.DefaultRuleEventListenerConfig
@ApplicationScoped
public class ProcessEventListenerConfig extends DefaultProcessEventListenerConfig {
public ProcessEventListenerConfig() {
super(new CustomProcessEventListener());
}
}
@ApplicationScoped
public class RuleEventListenerConfig extends DefaultRuleEventListenerConfig {
public RuleEventListenerConfig() {
super(new CustomRuleEventListener());
}
}
Note
|
These classes are meant to be injectable so ensure you properly annotate the class (@ApplicationScoped /@Component ) so they can be found and registered.
|
Kogito comes with base coverage for processes and rules evaluation. These can be directly exposed via HTTP endpoint. It is based on Prometheus and the content it serves is in that format as well so can be directly consumed by Prometheus server.
Add the following dependency to your project pom.xml
<dependency>
<groupId>org.kie.kogito</groupId>
<artifactId>monitoring-prometheus-addon</artifactId>
<version>${kogito.version}</version>
</dependency>
Depending on capabilities of Kogito used in the service you might register either or both of the following listeners
-
org.kie.kogito.monitoring.process.PrometheusProcessEventListener
-
org.kie.kogito.monitoring.rule.PrometheusMetricsDroolsListener
To enable process related metrics create ProcessEventListenerConfig class or add the Prometheus listener (org.kie.addons.monitoring.process.PrometheusProcessEventListener
) to already existing config class.
@ApplicationScoped
public class ProcessEventListenerConfig extends DefaultProcessEventListenerConfig {
public ProcessEventListenerConfig() {
super(new PrometheusProcessEventListener("acme-travels"));
}
}
To enable rule related metrics create RuleEventListenerConfig class or add the Prometheus listener (org.kie.addons.monitoring.rule.PrometheusMetricsDroolsListener
) to already existing config class.
@ApplicationScoped
public class RuleEventListenerConfig extends DefaultRuleEventListenerConfig {
public RuleEventListenerConfig() {
super(new PrometheusMetricsDroolsListener("acme-travels"));
}
}
Note
|
There is single argument for both classes and that is identifier that describes the data coming from the runtimes. It can be used to group the metrics later on when visualising them. |
See Persistence section to learn more about persistence and how to enable it.
Runtimes can produce events based on processed data. Currently this mainly applies to process execution but will most likely be expanded to cover also decisions and rules.
Runtime engine can emit events based on the execution context of given request (aka unit of work). The main aim for these events is to notify 3rd parties about changes to the process instance and its data.
To avoid too many events being sent and to optimise both producer and consumer side there will be only one event per process instance emitted.
That event will consists of relevant information such as
-
process instance metadata e.g. process id, process instance id, process instance state, etc
-
node instances executed, list of all node instances that have been triggered/left during the execution
-
variables - current state of variables after the execution
These events will provide complete view over the process instances being executed without need to respond to individual events that can be consumed via ProcessEventListener.
Important
|
these events are produced only when the execution finished successfully, meaning without any errors during the course of execution. |
In case there are multiple process instances executed within single request/unit of work each process instance will be given a dedicated event.
{
"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": 1565020069015,
"endDate": null,
"state": 1,
"nodeInstances": [
{
"id": "a8fe24c4-27a5-4869-85df-16e9f170f2c4",
"nodeId": "2",
"nodeDefinitionId": "CallActivity_1",
"nodeName": "Call a deal",
"nodeType": "SubProcessNode",
"triggerTime": 1565020069015,
"leaveTime": null
},
{
"id": "7a3bf1b1-b167-4928-969d-20bddf16c87a",
"nodeId": "1",
"nodeDefinitionId": "StartEvent_1",
"nodeName": "StartProcess",
"nodeType": "StartNode",
"triggerTime": 1565020069015,
"leaveTime": 1565020069015
}
],
"variables": {
"name": "my fancy deal",
"traveller": {
"firstName": "John",
"lastName": "Doe",
"email": "jon.doe@example.com",
"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 itself is in format of CloudEvent so can be easily consumed, it comes with few extensions to allow event routing based on the event metadata without looking into the body of the event
-
kogitoProcessinstanceId
-
kogitoParentProcessinstanceId
-
kogitoRootProcessinstanceId
-
kogitoProcessId
-
kogitoProcessinstanceState
-
type of the event is set to
ProcessInstanceEvent
In addition to process instance events, in case given execution (unit of work) makes any interactions with user tasks then additional event (one for each user task) will be produced.
That event will consists of relevant information such as
-
task metadata such as name, description, priority, start and complete dates
-
task input and output data
-
task assignments actual owner, potential users and groups, business admin and business admin groups, excluded users
-
task reference name that should be used to interact with the task via runtime service’s endpoints
{
"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": "jan.kowalski@email.com",
"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 itself is in format of CloudEvent so can be easily consumed, it comes with few extensions to allow event routing based on the event metadata without looking into the body of the event
-
kogitoUserTaskinstanceId
-
kogitoUserTaskinstanceState
-
kogitoProcessinstanceId
-
kogitoProcessId
-
type of the event is set to
UserTaskInstanceEvent
Events by default are only emitted when there is at least one publisher configured. There might be many event publishers that can be used to send/publish these events into different channels etc.
By default there are message based event publishers shipped with Kogito
-
Reactive message based that allows to send events to Kafka, AMQP, MQTT, Camel and this is used for Quarkus based runtimes
-
Spring Kafka based that allows to send events to Kafka and is dedicated to runtimes based on Spring Boot
Additional event producers can be developed by implementing org.kie.kogito.event.EventPublisher
that needs to be annotated with respective annotations for bean discovery.
Install Apache Kafka in the preferred way and create new topics named
-
kogito-processinstances-events
-
kogito-usertaskinstances-events
Add following into the pom.xml of the application.
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-reactive-messaging-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.kie.kogito</groupId>
<artifactId>kogito-events-reactive-messaging-addon</artifactId>
<version>${kogito.version}</version>
</dependency>
Edit application.properties
file located under src/main/resources
and add following entries
mp.messaging.outgoing.kogito-processinstances-events.connector=smallrye-kafka
mp.messaging.outgoing.kogito-processinstances-events.topic=kogito-processinstances-events
mp.messaging.outgoing.kogito-processinstances-events.value.serializer=org.apache.kafka.common.serialization.StringSerializer
mp.messaging.outgoing.kogito-usertaskinstances-events.connector=smallrye-kafka
mp.messaging.outgoing.kogito-usertaskinstances-events.topic=kogito-usertaskinstances-events
mp.messaging.outgoing.kogito-usertaskinstances-events.value.serializer=org.apache.kafka.common.serialization.StringSerializer
Start the application and on each request (that actually modifies the state of a process instance) you should see new messages to show up on the kogito-processinstances-events
topic. In addition, whenever there are user tasks interactions new messages should show up on 'kogito-usertaskinstances-events' topic.
Under heavy load for producer there might be error thrown in case the back pressure is overloaded. Use following property to disable waiting for completion which should make the overall throughput higher
mp.messaging.outgoing.kogito-processinstances-events.waitForWriteCompletion=false
mp.messaging.outgoing.kogito-usertaskinstances-events.waitForWriteCompletion=false
Install Apache Kafka in the preferred way and create new topics named
-
kogito-processinstances-events
-
kogito-usertaskinstances-events
Add following into the pom.xml of the application.
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.kie.kogito</groupId>
<artifactId>kogito-events-spring-boot-addon</artifactId>
<version>${kogito.version}</version>
</dependency>
@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());
}
}
Start the application and on each request (that actually modifies the state of a process instance) you should see new messages to show up on the kogito-processinstances-events
topic.
There are several application properties that allow to control the event publishing
-
kogito.events.processinstances.enabled
- allows to enable/disable publishing process instance events, defaults to true -
kogito.events.usertasks.enabled
- allows to enable/disable publishing user task instance events, defaults to true
By default Kogito services use in memory timer service to to handle time based events defined in the process. This does not cover long time intervals and is only suitable for short delays defined in the process. To allow for more advanced use cases where the time intervals can be of days or weeks or when there is extra handling required such as retries, Kogito Job Service can be used.
See details about Kogito Job Service here.
To enable Kogito Job Service to be used as timer service there are two steps required
-
Add dependency that is specific to the runtime your service is using (Quarkus or Spring Boot)
-
Configure locations of the Kogito Job Service and Callback
Add following dependency to your pom.xml
<dependency>
<groupId>org.kie.kogito</groupId>
<artifactId>jobs-management-quarkus-addon</artifactId>
</dependency>
Add following dependency to your pom.xml
<dependency>
<groupId>org.kie.kogito</groupId>
<artifactId>jobs-management-springboot-addon</artifactId>
</dependency>
Add following properties to application.properties
file to inform the Kogito Job Service add-on about locations of both Job Service itself and callback to be used when timer expires.
kogito.jobs-service.url=http://localhost:8085
kogito.service.url=http://localhost:8080
Note
|
Before this can be used, make sure that Kogito Job Service is started and the configuration given above is valid for its location. |
In case default settings of the rest clients used by the job service add-on are not sufficient, custom configured clients can be provided by the service implementors.
The top of rest client will differ depending on the runtime used
-
quarkus - uses Vert.x web client
io.vertx.ext.web.client.WebClient
-
spring boot - uses RestTemplate
org.springframework.web.client.RestTemplate
in both cases just product an instance of the above client to allow fine grained setup of the client.