Event-driven decisions with Kogito

In 2021 it’s almost undeniable that modern application development needs to target the cloud, given the requirements of flexibility, scalability and availability imposed by today’s world.

Event-driven architectures have proven to be well suited models for this purpose. As a result, we’re adopting these principles in several components of Kogito, which aims to be the next generation cloud-native business automation solution.

This blogpost presents a new component that aligns with this view: the event-driven decisions addon. It is available since Kogito v1.2.

Key concepts

This addon enables the evaluation of decision models in an event-driven fashion, so that it can be used as part of an event processing pipeline.

It comes in two flavours: Quarkus and Spring Boot.

The developer only needs to include the correct version as dependency of his Kogito app and configure the input/output topics. The wiring is done by the Kogito code-generation and framework specific dependency injection.

The execution is triggered upon receiving an event containing the initial context from a specific Kafka input topic. The result is then sent to a Kafka output topic (which may be the same). Both input and output events are formatted as CloudEvents.

Its capabilities are implemented to be similar to the ones available via REST endpoints:

  • trigger evaluation of the whole model or of a specific decision service
  • receive only the context or the full DMN result in the output event
  • filter out the inputs from the output context, no matter if returned alone or inside the DMN result

Event structure

Input event

A model evaluation is triggered by a specific event called DecisionRequest. Here is the list of the supported fields, including the optional ones:

FieldPurposeMandatoryDefault
dataInput contextyes
idCloudEvent IDyes
kogitodmnevaldecisionName of decision service to evaluate. If specified the engine triggers the evaluation of this service only.nonull
kogitodmnfilteredctxBoolean flag to enable/disable filtering out inputs from the contextnofalse
kogitodmnfullresultBoolean flag to enable/disable receiving full DMN result as outputnofalse
kogitodmnmodelnameName of DMN model to evaluateyes
kogitodmnmodelnamespaceNamespace of DMN model to evaluateyes
sourceCloudEvent sourceyes
specversionMust be equal to 1.0 as mandated by CloudEvent specificationyes
subjectIf specified, the engine will put the same value as subject of the output event. Its usage is up to the caller (e.g. as correlation ID).nonull
typeMust be equal to DecisionRequestyes

Example of DecisionRequest event

{
  "specversion": "1.0",
  "id": "a89b61a2-5644-487a-8a86-144855c5dce8",
  "source": "SomeEventSource",
  "type": "DecisionRequest",
  "kogitodmnmodelname": "Traffic Violation",
  "Kogitodmnmodelnamespace": "https://github.com/kiegroup/drools/kie-dmn/_A4BCA8B8-CF08-433F-93B2-A2598F19ECFF",
  "data": {
    "Driver": {
      "Age": 25,
      "Points": 13
    },
    "Violation": {
      "Type": "speed",
      "Actual Speed": 115,
      "Speed Limit": 100
    }
  }
}

Output events

If the request is evaluated successfully, the system returns two different types of output events depending on the value of the kogitodmnfullresult flag:

  • DecisionResponse if only the output context is returned
  • DecisionResponseFull if the full DMN result is returned

The results are always in the data field.

Example of DecisionResponse event

{
  "specversion": "1.0",
  "id": "d54ace84-6788-46b6-a359-b308f8b21778",
  "source": "Traffic+Violation",
  "type": "DecisionResponse",
  "kogitodmnmodelnamespace": "https://github.com/kiegroup/drools/kie-dmn/_A4BCA8B8-CF08-433F-93B2-A2598F19ECFF",
  "kogitodmnmodelname": "Traffic Violation",
  "data": {
    "Violation": {
      "Type": "speed",
      "Speed Limit": 100,
      "Actual Speed": 115
    },
    "calculateTotalPoints": "function calculateTotalPoints( driver, fine )",
    "Driver": {
      "Points": 13,
      "Age": 25
    },
    "Fine": {
      "Points": 3,
      "Amount": 500
    },
    "Should the driver be suspended?": "No"
  }
}

Example of DecisionResponseFull event

{
  "specversion": "1.0",
  "id": "a18c409d-ab1f-4d6b-abc7-97327df8585f",
  "source": "Traffic+Violation",
  "type": "DecisionResponseFull",
  "kogitodmnmodelnamespace": "https://github.com/kiegroup/drools/kie-dmn/_A4BCA8B8-CF08-433F-93B2-A2598F19ECFF",
  "kogitodmnmodelname": "Traffic Violation",
  "data": {
    "namespace": "https://github.com/kiegroup/drools/kie-dmn/_A4BCA8B8-CF08-433F-93B2-A2598F19ECFF",
    "modelName": "Traffic Violation",
    "dmnContext": {
      "Violation": {
        "Type": "speed",
        "Speed Limit": 100,
        "Actual Speed": 115
      },
      "calculateTotalPoints": "function calculateTotalPoints( driver, fine )",
      "Driver": {
        "Points": 13,
        "Age": 25
      },
      "Fine": {
        "Points": 3,
        "Amount": 500
      },
      "Should the driver be suspended?": "No"
    },
    "messages": [],
    "decisionResults": [
      {
        "decisionId": "_4055D956-1C47-479C-B3F4-BAEB61F1C929",
        "decisionName": "Fine",
        "result": {
          "Points": 3,
          "Amount": 500
        },
        "messages": [],
        "evaluationStatus": "SUCCEEDED"
      },
      {
        "decisionId": "_8A408366-D8E9-4626-ABF3-5F69AA01F880",
        "decisionName": "Should the driver be suspended?",
        "result": "No",
        "messages": [],
        "evaluationStatus": "SUCCEEDED"
      }
    ]
  }
}

Error events

If, for some reason, the request event is malformed or contains wrong information so that the evaluation can’t be triggered, a DecisionResponseError is sent as output.

In this case the data field contains a string that specifies the error type:

Error TypeMeaning
BAD_REQUESTMalformed input event (e.g. when some mandatory fields are missing)
MODEL_NOT_FOUNDThe specified model can’t be found in the current service

Examples

The Kogito Examples repository contains two examples, one for Quarkus and one for Spring Boot, that you can use as a starting point to practice with this addon.

They also contain tests for every possible variation in the structure of the input/output events supported by the addon.

Conclusion

If you liked this article and are interested in the evolution of Kogito, stay tuned for more news!

Thanks for reading.

0 0 votes
Article Rating
Subscribe
Notify of
guest
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments