Quarkus - Using Kogito to add business automation capabilities to an application

    Kogito is a next generation business automation toolkit that originates from well known Open Source projectsDrools (for business rules) and jBPM (for business processes). Kogito aims at providing another approachto business automation where the main message is to expose your business knowledge (processes, rules and decisions)in a domain specific way.

    To complete this guide, you need:

    • less than 15 minutes

    • an IDE (Eclipse is preferred with the BPMN modeller plugin)

    • JDK 1.8+ installed with configured appropriately

    • Apache Maven 3.5.3+

    • Docker

    Kogito Tooling is currently supported in Eclipse and VSCode:

    • Eclipse

    To be able to make use of visual modelling of your processes, download Eclipse IDE andinstall from Market place Eclipse BPMN2 Modeller plugin (with jBPM Runtime Extension)

    • VSCode

    Download and install the VSCode Extension from to edit and model process definitions from VSCode IDE.

    Architecture

    In this example, we build a very simple microservice which offers one REST endpoint:

    • /persons

    This endpoint will be automatically generated based on business process, that in turn willmake use of business rules to make certain decisions based on the data being processed.

    Business process

    The business process will be responsible for encapsulating business logic of our microservice.It should provide complete set of steps to achieve a business goal.At the same time this is the entry point to the service that can be consumed by clients.

    Business rule

    A business rule allows to externalise decision logic into reusable pieces that can be easilyused in declarative way. There are multiple ways of writing rules like decision tables,decision trees, rules, etc. For this example we focus on the rule format backed by DRL(Drools Rule Language).

    Solution

    We recommend that you follow the instructions in the next sections and create the application step by step.However, you can go right to the complete example.

    Clone the Git repository: git clone https://github.com/quarkusio/quarkus-quickstarts.git, or download an .

    The solution is located in the kogito-quickstart directory.

    First, we need a new project. Create a new project with the following command:

    This command generates a Maven project, importing the kogito extensionthat comes with all needed dependencies and configuration to equip your applicationwith business automation.

    Writing the application

    Let’s start by implementing the simple data object Person. As you can see from the source code below it is just a POJO:

    1. package org.acme.kogito.model;
    2. public class Person {
    3. private String name;
    4. private int age;
    5. private boolean adult;
    6. public String getName() {
    7. return name;
    8. }
    9. public void setName(String name) {
    10. this.name = name;
    11. }
    12. public int getAge() {
    13. return age;
    14. }
    15. this.age = age;
    16. }
    17. public boolean isAdult() {
    18. return adult;
    19. }
    20. public void setAdult(boolean adult) {
    21. this.adult = adult;
    22. }
    23. @Override
    24. public String toString() {
    25. return "Person [name=" + name + ", age=" + age + ", adult=" + adult + "]";
    26. }
    27. }

    Next, we create a rule file person-rules.drl inside the src/main/resources/org/acme/kogito folder ofthe generated project.

    1. package org.acme.kogito
    2. import org.acme.kogito.model.Person;
    3. rule "Is adult" ruleflow-group "person"
    4. when
    5. $person: Person(age > 18)
    6. then
    7. modify($person) {
    8. setAdult(true)
    9. };
    10. end

    This is really a simple rule that marks a person who is older that 18 years as an adult.

    Finally we create a business process that will make use of this rule and some otheractivities to approve a given person. Using new item wizard (File → New → Other → BPMN2 Model)create persons.bpmn inside src/main/resources/org/acme/kogito folder of the generated project.

    This process should consist of

    • business rule task

    • exclusive gateway

    • user task

    • end events

    And should look like

    To get started quickly copy the process definition from the

    To model this process yourself, just follow these steps (start event should be automatically added)

    • define a process variable with name person of type org.acme.kogito.model.Person

    • drag the Tasks → Business Rule Task from the palette and drop it next to start event, link it with start event

    • double click on the business rule task
    1. -

    on tab I/O Parameters, set data input and output (map person process variable to input data with name person and same for data output)

    1. -

    on tab Business Rule Task, set rule flow group to the value defined in the drl file (person)

    • drag the Gateways → XOR gateway from the palette and drop it next to the business rule task, link it with rule task

    • drag the Tasks → User Task from the palette and drop it next to the gateway, link it with gateway

    • double click on the user task
    1. -

    on tak User Task, set task name to ChildrenHandling

    1. -

    on tab I/O Parameters, set data input (map person process variable to input data with name person)

    • drag the End Events → End from the palette and drop it next to the user task, link it with the user task

    • double click on the gateway

    • on tab Gateway, set the diverging direction for the gateway

    • on tab Gateway, set conditions on sequence flow list

    1. -

    → going to end event return person.isAdult() == true; with language Java

    → going to user task return person.isAdult() == false; with language Java

    • save the file

    Running and Using the Application

    To run the microservice in dev mode, use ./mvnw clean compile quarkus:dev.

    Running in JVM Mode

    First compile it:

    1. ./mvnw package

    Then run it:

    1. java -jar ./target/kogito-quickstart-runner.jar

    Running in Native Mode

    This same demo can be compiled into native code: no modifications required.

    This implies that you no longer need to install a JVM on yourproduction environment, as the runtime technology is included inthe produced binary, and optimized to run with minimal resource overhead.

    Compilation will take a bit longer, so this step is disabled by default;let’s build again by enabling the native profile:

    1. ./mvnw package -Dnative

    After getting a cup of coffee, you’ll be able to run this binary directly:

    To test your application, just send request to the service with giving the person as JSONpayload.

    1. curl -X POST http://localhost:8080/persons \
    2. -H 'content-type: application/json' \
    3. -H 'accept: application/json' \
    4. -d '{"person": {"name":"John Quark", "age": 20}}'

    In the response, the person should be approved as an adult and that should also be visible in the response payload.

    1. {"id":"dace1d6a-a5fa-429d-b253-d6b66e265bbc","person":{"adult":true,"age":20,"name":"John Quark"}}

    You can also verify that there are no more active instances

    1. curl -X GET http://localhost:8080/persons \
    2. -H 'content-type: application/json' \
    3. -H 'accept: application/json'

    To verify the non adult case, send another request with the age set to less than 18

    this time there should be one active instance, replace {uuid} with the id attribute taken from the response

    1. curl -X GET http://localhost:8080/persons/{uuid}/tasks \
    2. -H 'content-type: application/json' \
    3. -H 'accept: application/json'

    You can get the details of the task by calling another endpoint, replace uuids with the values taken fromthe responses (uuid-1 is the process instance id and uuid-2 is the task instance id).First corresponds to the process instance id and the other to the task instance id.

    1. curl -X GET http://localhost:8080/persons/{uuid-1}/ChildrenHandling/{uuid-2} \
    2. -H 'content-type: application/json' \
    3. -H 'accept: application/json'

    You can complete this person evaluation process instance by calling the same endpoint but with POST,replace uuids with the values taken from the responses (uuid-1 is the process instance id and uuid-2 is the task instance id).

    1. curl -X POST http://localhost:8080/persons/{uuid-1}/ChildrenHandling/{uuid-2} \
    2. -H 'content-type: application/json' \
    3. -H 'accept: application/json' \
    4. -d '{}'

    Enabling persistence

    Since 0.3.0 of Kogito, there is an option to enable persistence to preserve process instance stateacross application restarts. That supports long running process instances that can be resumed at anypoint in time.

    Kogito uses Infinispan as the persistence service so you need to have Infinispan server installed and running.Version of the Infinispan is aligned with Quarkus BOM so make sure the right version is installed.

    Add dependencies to project

    1. <dependency>
    2. <groupId>io.quarkus</groupId>
    3. <artifactId>quarkus-infinispan-client</artifactId>
    4. </dependency>
    5. <dependency>
    6. <groupId>org.kie.kogito</groupId>
    7. <artifactId>infinispan-persistence-addon</artifactId>
    8. <version>${kogito.version}</version>
    9. </dependency>

    Configure connection with Infinispan server

    Add following into the src/main/resources/application.properties file (create the file if it does not exist)

    1. quarkus.infinispan-client.server-list=localhost:11222

    After configuring persistence on the project level, you can test and verify that the process instancestate is preserved across application restarts.

    • start Infinispan server

    • build and run your project

    • execute non adult use case

    1. curl -X POST http://localhost:8080/persons \
    2. -H 'content-type: application/json' \
    3. -H 'accept: application/json' \
    4. -d '{"person": {"name":"Jenny Quark", "age": 15}}'

    You can also verify that there is active instance

    1. curl -X GET http://localhost:8080/persons \
    2. -H 'content-type: application/json' \

    Restart your application while keeping Infinispan server up and running.

    Check if you can see active instance which should have exactly the same id

    To learn more about persistence in Kogito visit this page

    References