diff --git a/README.md b/README.md index 31fe7ba742..1af1e96b9b 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,7 @@ shows timers (intermediate and boundary) that allows to introduce delays in proc - Onboarding example combining 1 process and two decision services: see [README.md](onboarding-example/README.md) - Rules on Quarkus: see [README.md](rules-quarkus-example/README.md) - Rules on Quarkus with Unit: see [README.md](ruleunit-quarkus-example/README.md) +- Straight-through Process (STP) orchestrating decisions and rules with Kogito Runtime Tools Quarkus extension: see [README.md](straight-through-process-decisions-quarkus-devservices/README.md) - Process on Quarkus: see [README.md](process-quarkus-example/README.md) - Process on Spring Boot: see [README.md](process-springboot-example/README.md) diff --git a/process-decisions-quarkus/README.md b/process-decisions-quarkus/README.md index bc72a4ec48..05104b0eff 100644 --- a/process-decisions-quarkus/README.md +++ b/process-decisions-quarkus/README.md @@ -2,14 +2,16 @@ ## Description -This is an example project that shows the usage of decisions within processes. Decisions can be expressed in different domains or assets, such as DMN and DRL. +This is a straight-through process (STP) example intended to orchestrate business decisions using BPMN. Decisions can be expressed in different domains or assets, such as DMN and DRL. The focus here is to show how to integrate decisions in an embedded way using Business Rule Task where they must be deployed together with the process, in the same application. All assets(bpmn, dmn, drl) must be under the [resources](src/main/resources/). This example covers the following items: +* Straight-through process (no state persistence) * DMN to define a decision service * DRL to define rules decision service * How to integrate the process with decisions using Business Rule Task +* Kogito Runtime Tools Quarkus extension to leverage the Management Console during dev time ### The Traffic Process example: @@ -181,9 +183,9 @@ Given data: { "driverId": "12345", "violation":{ - "Type":"speed", - "Speed Limit": 100, - "Actual Speed":140 + "type":"speed", + "speedLimit": 100, + "actualSpeed":140 } } ``` @@ -236,9 +238,9 @@ Given data: { "driverId": "1234", "violation":{ - "Type":"speed", - "Speed Limit": 100, - "Actual Speed":110 + "type":"speed", + "speedLimit": 100, + "actualSpeed":110 } } ``` @@ -278,7 +280,44 @@ After the Curl command, you should see a similar console log ``` In this case the driver license is expired when the DRL is evaluated because the DriverService generated an expired date for the driver's license thus DMN is not evaluated, so the `validLicense` is `false`, `suspended` and `fine` are `null`. +## Using the Management Console and Kogito Runtime Tools +This projects includes a Maven profile that allows you to start the service with the new [Kogito Runtime Tools Quarkus extension](https://blog.kie.org/2021/09/developing-business-processes-more-efficiently-with-runtime-tools-quarkus-extension-part-1.html) allowing you as a developer access the [Kogito Management Console](https://blog.kie.org/2021/09/manage-processes-and-tasks-using-kogito-consoles.html) and visualize your Process Instances. + +Although the Business Process used in this example project is a STP and do not have state persistence, we are leveraging the Kogito Data Index service to store the Process Instance runtime events (process definition, variables, process nodes, meta-data etc) so we can visualize the final state of each instance using the Kogito Management Console. In order to do that we need to start the Data Index service and its backend components (Kafka and Infinispan). For this we provide a docker-compose file inside [docker-compose](./docker-compose) directory. + +### Prerequisites + +You will need: + - Kogito Data Index Service and its required components: Kafka and Infinispan + - Docker and Docker Compose + +### Kogito Management Console +In order to visualize the Process Instance Diagram and its Completed Status you need to start the service using the `runtime-tools` maven profile: + +``` +mvn clean compile quarkus:dev -Pruntime-tools +``` + +This profile leverages a new Quarkus extension provided by Kogito that brings the Management Console as part of the Quarkus Dev Services UI. +After starting your Kogito app using this profile (`-Pruntime-tools`) access the Quarkus [Dev UI](http://localhost:8080/q/dev/) at http://localhost:8080/q/dev + +On the **Kogito Runtime Tools** Card click on **Process Instances** + +![Quarkus Dev UI](docs/images/DevUI.png) + +If you have already started any process instance by calling the Kogito Rest API endpoint you will be able to see them by filtering them by `Completed`. + +![Process Instances Filter](docs/images/DevUI-processInstances_completed.png) + +Your completed process instances should appear in a list like this + +![Processes List](docs/images/DevUI_processInstance_list.png) + +Click in any process to see its details + +![Processes List](docs/images/DevUI_processInstance_detail.png) +> The Management Console get these information from the Kogito Data Index service which is responsible for consuming Process events from Kafka index them and store into Infinispan. ## Deploying with Kogito Operator In the [`operator`](operator) directory you'll find the custom resources needed to deploy this example on OpenShift with the [Kogito Operator](https://docs.jboss.org/kogito/release/latest/html_single/#chap_kogito-deploying-on-openshift). \ No newline at end of file diff --git a/process-decisions-quarkus/docker-compose/README.md b/process-decisions-quarkus/docker-compose/README.md new file mode 100644 index 0000000000..b38a894afc --- /dev/null +++ b/process-decisions-quarkus/docker-compose/README.md @@ -0,0 +1,47 @@ +## Kogito and Infrastructure services + +To allow a quick setup of all the required services to run this demo, we provide a Docker Compose template that starts the following services: +- Infinispan +- Kafka +- Kogito Data Index + +In order to use it, please ensure you have Docker Compose installed on your machine, otherwise follow the instructions available + in [here](https://docs.docker.com/compose/install/). + +### Starting required services + + Before you execute the **Hiring** example, start all the services by following these steps: + + For Linux and MacOS: + + ./startServices.sh + + For Windows: + + 1. Create a .env file with the content containing the version of the Kogito images you would like to run, + for example: + + KOGITO_VERSION=1.0.0 + + 2. Execute the following command. + + docker-compose -p kogito-services up -d + + Once all services bootstrap, the following ports will be assigned on your local machine: + - Infinispan: 11222 + - Kafka: 9092 + - Data Index: 8180 + +### Stopping and removing volume data + + To stop all services, simply run: + + docker-compose stop + + It is also recommended to remove any of stopped containers by running: + + docker-compose rm + + For more details please check the Docker Compose documentation. + + docker-compose --help diff --git a/process-decisions-quarkus/docker-compose/docker-compose.yml b/process-decisions-quarkus/docker-compose/docker-compose.yml new file mode 100755 index 0000000000..b1f39363cd --- /dev/null +++ b/process-decisions-quarkus/docker-compose/docker-compose.yml @@ -0,0 +1,81 @@ +version: '2.1' + +services: + + infinispan: + image: infinispan/server:12.1.7.Final + container_name: infinispan + ports: + - 11222:11222 + command: "/opt/infinispan/bin/server.sh -c infinispan-demo.xml" + volumes: + - ./infinispan/infinispan.xml:/opt/infinispan/server/conf/infinispan-demo.xml:z + healthcheck: + test: [ "CMD", "curl", "-f", "http://localhost:11222/rest/v2/cache-managers/default/health/status" ] + interval: 1s + timeout: 30s + retries: 50 + + zookeeper: + container_name: zookeeper + image: strimzi/kafka:0.20.1-kafka-2.6.0 + command: [ + "sh", "-c", + "bin/zookeeper-server-start.sh config/zookeeper.properties" + ] + ports: + - "2181:2181" + environment: + LOG_DIR: "/tmp/logs" + + kafka: + image: strimzi/kafka:0.20.1-kafka-2.6.0 + container_name: kafka + command: [ + "sh", "-c", + "bin/kafka-server-start.sh config/server.properties --override inter.broker.listener.name=$${KAFKA_INTER_BROKER_LISTENER_NAME} --override listener.security.protocol.map=$${KAFKA_LISTENER_SECURITY_PROTOCOL_MAP} --override listeners=$${KAFKA_LISTENERS} --override advertised.listeners=$${KAFKA_ADVERTISED_LISTENERS} --override zookeeper.connect=$${KAFKA_ZOOKEEPER_CONNECT}" + ] + depends_on: + - zookeeper + ports: + - "9092:9092" + environment: + KAFKA_BROKER_ID: 0 + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_LISTENERS: INTERNAL://kafka:29092,EXTERNAL://kafka:9092 + KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:29092,EXTERNAL://localhost:9092 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT + KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL + KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true" + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + LOG_DIR: "/tmp/logs" + + kafdrop: + image: obsidiandynamics/kafdrop + container_name: kafdrop + restart: "no" + ports: + - "9000:9000" + environment: + KAFKA_BROKERCONNECT: kafka:29092 + JVM_OPTS: "-Xms16M -Xmx48M -Xss180K -XX:-TieredCompilation -XX:+UseStringDeduplication -noverify" + depends_on: + - "kafka" + + data-index: + container_name: data-index + image: quay.io/kiegroup/kogito-data-index-infinispan:${KOGITO_VERSION} + ports: + - "8180:8080" + depends_on: + kafka: + condition: service_started + infinispan: + condition: service_healthy + volumes: + - ./persistence/:/home/kogito/data/protobufs/ + environment: + QUARKUS_INFINISPAN_CLIENT_SERVER_LIST: infinispan:11222 + QUARKUS_INFINISPAN_CLIENT_USE_AUTH: "false" + KAFKA_BOOTSTRAP_SERVERS: kafka:29092 + KOGITO_DATA_INDEX_PROPS: -Dkogito.protobuf.folder=/home/kogito/data/protobufs/ \ No newline at end of file diff --git a/process-decisions-quarkus/docker-compose/infinispan/infinispan.xml b/process-decisions-quarkus/docker-compose/infinispan/infinispan.xml new file mode 100755 index 0000000000..c5899af923 --- /dev/null +++ b/process-decisions-quarkus/docker-compose/infinispan/infinispan.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/process-decisions-quarkus/docker-compose/startServices.sh b/process-decisions-quarkus/docker-compose/startServices.sh new file mode 100755 index 0000000000..db04d077e3 --- /dev/null +++ b/process-decisions-quarkus/docker-compose/startServices.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +echo "Script requires your Kogito Quickstart to be compiled" + +PROJECT_VERSION=$(cd ../ && mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + +echo "Project version: ${PROJECT_VERSION}" + +if [[ $PROJECT_VERSION == *SNAPSHOT ]]; +then + KOGITO_VERSION="latest" +else + KOGITO_VERSION=${PROJECT_VERSION%.*} +fi + +echo "Kogito Image version: ${KOGITO_VERSION}" +echo "KOGITO_VERSION=${KOGITO_VERSION}" > ".env" + +if [ "$(uname)" == "Darwin" ]; then + echo "DOCKER_GATEWAY_HOST=host.docker.internal" >> ".env" +elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then + echo "DOCKER_GATEWAY_HOST=172.17.0.1" >> ".env" +fi + +SVG_FOLDER=./svg + +KOGITO_EXAMPLE_SVG_FOLDER=../target/classes/META-INF/processSVG + +mkdir -p $SVG_FOLDER + +if [ -d "$KOGITO_EXAMPLE_SVG_FOLDER" ] +then + cp $KOGITO_EXAMPLE_SVG_FOLDER/*.svg $SVG_FOLDER +else + echo "$KOGITO_EXAMPLE_SVG_FOLDER does not exist. Have you compiled the project?" + exit 1 +fi + +docker-compose -p kogito-services up -d \ No newline at end of file diff --git a/process-decisions-quarkus/docker-compose/svg/traffic.svg b/process-decisions-quarkus/docker-compose/svg/traffic.svg new file mode 100644 index 0000000000..fb2ed0d35f --- /dev/null +++ b/process-decisions-quarkus/docker-compose/svg/traffic.svg @@ -0,0 +1 @@ +TrafficViolation DMN Not Suspended Task Suspended Task Get Driver Details LicenseValidation DRL license is expired license is valid yes no \ No newline at end of file diff --git a/process-decisions-quarkus/docs/images/DevUI-processInstances_completed.png b/process-decisions-quarkus/docs/images/DevUI-processInstances_completed.png new file mode 100644 index 0000000000..08ddb684e8 Binary files /dev/null and b/process-decisions-quarkus/docs/images/DevUI-processInstances_completed.png differ diff --git a/process-decisions-quarkus/docs/images/DevUI.png b/process-decisions-quarkus/docs/images/DevUI.png new file mode 100644 index 0000000000..eb1997e1c5 Binary files /dev/null and b/process-decisions-quarkus/docs/images/DevUI.png differ diff --git a/process-decisions-quarkus/docs/images/DevUI_processInstance_detail.png b/process-decisions-quarkus/docs/images/DevUI_processInstance_detail.png new file mode 100644 index 0000000000..369e2c211f Binary files /dev/null and b/process-decisions-quarkus/docs/images/DevUI_processInstance_detail.png differ diff --git a/process-decisions-quarkus/docs/images/DevUI_processInstance_list.png b/process-decisions-quarkus/docs/images/DevUI_processInstance_list.png new file mode 100644 index 0000000000..b7caf47348 Binary files /dev/null and b/process-decisions-quarkus/docs/images/DevUI_processInstance_list.png differ diff --git a/process-decisions-quarkus/pom.xml b/process-decisions-quarkus/pom.xml index bf1fef1168..9d58c87228 100644 --- a/process-decisions-quarkus/pom.xml +++ b/process-decisions-quarkus/pom.xml @@ -9,7 +9,7 @@ process-decisions-quarkus Kogito Example :: Process :: Decisions :: Quarkus - Process with DMN and DRL integration - Quarkus + Straight-through Process with DMN and DRL integration - Quarkus @@ -67,4 +67,52 @@ + + + runtime-tools + + quarkus-bom + io.quarkus + 2.4.0.Final + runtime-tools + + + + + org.kie.kogito + kogito-quarkus-bom + ${kogito.version} + pom + import + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + + + + org.kie.kogito + kogito-addons-quarkus-process-svg + + + org.kie.kogito + kogito-addons-quarkus-events-process + + + io.quarkus + quarkus-smallrye-reactive-messaging-kafka + + + org.kie.kogito + runtime-tools-quarkus-extension + ${kogito.version} + + + + \ No newline at end of file diff --git a/process-decisions-quarkus/src/main/resources/META-INF/processSVG/traffic.svg b/process-decisions-quarkus/src/main/resources/META-INF/processSVG/traffic.svg new file mode 100644 index 0000000000..fb2ed0d35f --- /dev/null +++ b/process-decisions-quarkus/src/main/resources/META-INF/processSVG/traffic.svg @@ -0,0 +1 @@ +TrafficViolation DMN Not Suspended Task Suspended Task Get Driver Details LicenseValidation DRL license is expired license is valid yes no \ No newline at end of file diff --git a/process-decisions-quarkus/src/main/resources/application-runtime-tools.properties b/process-decisions-quarkus/src/main/resources/application-runtime-tools.properties new file mode 100644 index 0000000000..e97e0e0685 --- /dev/null +++ b/process-decisions-quarkus/src/main/resources/application-runtime-tools.properties @@ -0,0 +1,36 @@ +# Kafka Connection +kafka.bootstrap.servers=localhost:9092 + +# Kogito Events config +kogito.events.processinstances.enabled=true +kogito.events.variables.enabled=true +kogito.events.usertasks.enabled=false + +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 + +mp.messaging.outgoing.kogito-variables-events.connector=smallrye-kafka +mp.messaging.outgoing.kogito-variables-events.topic=kogito-variables-events +mp.messaging.outgoing.kogito-variables-events.value.serializer=org.apache.kafka.common.serialization.StringSerializer + +# Data-index service URL +kogito.dataindex.http.url=http://localhost:8180 +kogito.dataindex.ws.url=ws://localhost:8180 +# ISPN Connection +quarkus.infinispan-client.server-list=localhost:11222 +quarkus.infinispan-client.use-auth=false + +org.kie.kogito.runtime.tools.quarkus.extension.runtime.dataindex.DataIndexClient/mp-rest/url=http://localhost:8180 +# Mocked users and groups for the task inbox screen +quarkus.kogito-runtime-tools.users=jdoe,admin,user +quarkus.kogito-runtime-tools.users.jdoe.groups=admin +quarkus.kogito-runtime-tools.users.admin.groups=admin +quarkus.kogito-runtime-tools.users.user.groups=user + +quarkus.test.continuous-testing=disabled +quarkus.devservices.enabled=true \ No newline at end of file