diff --git a/03-kogito-travel-agency/.gitignore b/03-kogito-travel-agency/.gitignore
new file mode 100644
index 00000000000..dc611a28acb
--- /dev/null
+++ b/03-kogito-travel-agency/.gitignore
@@ -0,0 +1,18 @@
+bin/
+/target
+/local
+
+# Eclipse, Netbeans and IntelliJ files
+/.*
+!.gitignore
+/nbproject
+/*.ipr
+/*.iws
+/*.iml
+
+# Repository wide ignore mac DS_Store files
+.DS_Store
+*~
+/settings*.xml
+*.db
+*.tlog
diff --git a/03-kogito-travel-agency/README.md b/03-kogito-travel-agency/README.md
new file mode 100644
index 00000000000..f6cb9fbfdd5
--- /dev/null
+++ b/03-kogito-travel-agency/README.md
@@ -0,0 +1,331 @@
+# Kogito Travel Agency
+
+
+NOTE: This requires Kogito 0.3.0 that is not yet released and that's why it refers to snapshot versions
+for both Kogito and Quarkus
+
+## Description
+
+During this workshop we will create a software system for a startup travel agency called Kogito Travel Agency. The first iteration of the system will consist of a set of services that are able to deal with travel requests and the booking of hotels and flights. In addition to that, in case visa is required for the traveller
+she will be given a chance to apply for visa and by that send visa application automatically to Kogito Visas service.
+
+## Activities to perform
+
+* Create project using Quarkus Maven plugin with following extensions
+ * Kogito
+ * OpenApi
+* Import project into Eclipse IDE - requires BPMN modeller plugin installed
+* Create data model
+ * Traveller
+ * Hotel
+ * Flight
+ * Address
+ * Trip
+ * VisaApplication
+* Create service classes
+ * HotelBookingService
+ * FlightBookingService
+* Create decision logic
+ * Visa check
+* Create business logic
+ * Public business process to deal with complete travel request
+ * Private business process to deal with hotel booking
+ * Private business process to deal with flight booking
+* Create a test case that makes use of processes and decisions
+* Configure messaging and events
+* Create or import UI components
+* Add metrics support for processes and decisions
+* Create dashboard based on metrics
+
+## Data model
+
+Kogito Travel Agency booking system will be based on following data model
+
+**Traveller**
+
+A person who requests a new travel
+
+**Trip**
+
+Place/Location where the traveller wants to go and dates
+
+**Flight**
+
+Flight that has been booked for the traveller to take him/her to the destination
+
+**Hotel**
+
+Place/Location where the traveller will stay during his/her travel
+
+**Address**
+
+Location that is associated with either traveller or hotel
+
+
+
+
+## Decision logic
+
+The decision logic will be implemented as a decision table. The logic will be responsible for verifying whether a given traveller requires a visa to enter a given country or not. The decision logic reason over the following data/facts
+
+* Destination that the traveller wants to go - country
+* Nationality of the traveller
+* Length of the stay
+
+The result will be “yes” or “no”.
+
+
+
+
+## Business logic
+
+Business logic will be based on business processes
+
+Public process that will be responsible for orchestrating complete travel request
+
+
+
+Private process that will be responsible for booking a hotel.
+
+
+
+Private process that will be responsible for booking a flight.
+
+
+
+## Services
+
+There will be services implemented to carry on the hotel and flight booking. Implementation will be a CDI beans that will have hard coded logic to return a booked flight or hotel.
+
+* org.acme.travels.service.HotelBookingService
+* org.acme.travels.service.FlightBookingService
+
+
+
+# Try out the complete service
+
+## Installing and Running
+
+### Prerequisites
+
+You will need:
+ - Java 1.8.0+ installed
+ - Environment variable JAVA_HOME set accordingly
+ - Maven 3.5.4+ installed
+
+When using native image compilation, you will also need:
+ - GraalVM installed
+ - Environment variable GRAALVM_HOME set accordingly
+ - Note that GraalVM native image compilation typically requires other packages (glibc-devel, zlib-devel and gcc) to be installed too, please refer to GraalVM installation documentation for more details.
+
+### Infrastructure requirements
+
+#### Infinispan
+
+This application requires an Inifinispan server to be available and by default expects it to be on default port and localhost.
+
+You can install Inifinispan server by downloading it from [https://infinispan.org/download/](official website) version to be used in 10.0.0.Beta4
+
+
+#### Apache Kafka
+
+This application requires a Apache Kafka installed and following topics created
+
+* `visaapplications` - used to send visa application that are consumed and processed by Kogito Visas service
+* `kogito-processinstances-events` - used to emit events by kogito that can be consumed by data index service and other services
+
+
+### Compile and Run in Local Dev Mode
+
+```
+mvn clean package quarkus:dev
+```
+
+NOTE: With dev mode of Quarkus you can take advantage of hot reload for business assets like processes, rules and decision
+tables and java code. No need to redeploy or restart your running application.During this workshop we will create a software system for a startup travel agency called Kogito Travel Agency. The first iteration of the system will consist of a set of services that are able to deal with travel requests and the booking of hotels and flights.
+
+
+### Compile and Run using Local Native Image
+Note that this requires GRAALVM_HOME to point to a valid GraalVM installation
+
+```
+mvn clean package -Pnative
+```
+
+To run the generated native executable, generated in `target/`, execute
+
+```
+./target/kogito-travel-agency-{version}-runner
+```
+
+## Known issues
+
+
+## User interface
+
+Kogito Travel Agency comes with basic UI that allows to
+
+### plan new trips
+
+
+
+### list currently opened travel requests
+
+
+
+### show details of selected travel request
+
+
+
+### show active tasks of selected travel request
+
+
+
+### cancel selected travel request
+
+To start Kogito Travel Agency UI just point your browser to [http://localhost:8080](http://localhost:8080)
+
+## REST API
+
+Once the service is up and running, you can use the following examples to interact with the service.
+
+### POST /travels
+
+Send travel that requires does not require visa
+
+```sh
+curl -H "Content-Type: application/json" -H "Accept: application/json" -X POST http://localhost:8080/travels -d @- << EOF
+{
+ "traveller" : {
+ "firstName" : "John",
+ "lastName" : "Doe",
+ "email" : "john.doe@example.com",
+ "nationality" : "American",
+ "address" : {
+ "street" : "main street",
+ "city" : "Boston",
+ "zipCode" : "10005",
+ "country" : "US"
+ }
+ },
+ "trip" : {
+ "city" : "New York",
+ "country" : "US",
+ "begin" : "2019-12-10T00:00:00.000+02:00",
+ "end" : "2019-12-15T00:00:00.000+02:00"
+ }
+}
+EOF
+
+```
+
+This will directly go to 'ConfirmTravel' user task.
+
+Send travel request that requires does require visa
+
+```sh
+curl -H "Content-Type: application/json" -H "Accept: application/json" -X POST http://localhost:8080/travels -d @- << EOF
+{
+ "traveller" : {
+ "firstName" : "Jan",
+ "lastName" : "Kowalski",
+ "email" : "jan.kowalski@example.com",
+ "nationality" : "Polish",
+ "address" : {
+ "street" : "polna",
+ "city" : "Krakow",
+ "zipCode" : "32000",
+ "country" : "Poland"
+ }
+ },
+ "trip" : {
+ "city" : "New York",
+ "country" : "US",
+ "begin" : "2019-12-10T00:00:00.000+02:00",
+ "end" : "2019-12-15T00:00:00.000+02:00"
+ }
+}
+EOF
+```
+
+This will stop at 'VisaApplication' user task.
+
+### GET /travels
+
+Returns list of travel requests currently active:
+
+```sh
+curl -X GET http://localhost:8080/travels
+```
+
+As response an array of travels is returned.
+
+### GET /travels/{id}
+
+Returns travel request with given id (if active):
+
+```sh
+curl -X GET http://localhost:8080/travels/{uuid}
+```
+
+As response a single travel request is returned if found, otherwise no content (204) is returned.
+
+### DELETE /travels/{id}
+
+Cancels travel request with given id
+
+```sh
+curl -X DELETE http://localhost:8080/travels/{uuid}
+```
+
+### GET /travels/{id}/tasks
+
+Returns currently assigned user tasks for give travel request:
+
+```sh
+curl -X GET http://localhost:8080/travels/{uuid}/tasks
+```
+
+### GET /travels/{id}/VisaApplication/{taskId}
+
+Returns visa application task information:
+
+```sh
+curl -X GET http://localhost:8080/travels/{uuid}/VisaApplication/{task-uuid}
+```
+
+### POST /travels/{id}/VisaApplication/{taskId}
+
+Completes visa application task
+
+```sh
+curl -H "Content-Type: application/json" -H "Accept: application/json" -X POST http://localhost:8080/travels/{uuid}/VisaApplication/{task-uuid} -d @- << EOF
+{
+ "visaApplication" : {
+ "firstName" : "Jan",
+ "lastName" : "Kowalski",
+ "nationality" : "Polish",
+ "city" : "New York",
+ "country" : "US",
+ "passportNumber" : "ABC09876",
+ "duration" : 25
+ }
+}
+EOF
+```
+
+### GET /travels/{id}/ConfirmTravel/{taskId}
+
+Returns travel (hotel, flight) task information required for confirmation:
+
+```sh
+curl -X GET http://localhost:8080/travels/{uuid}/tasks/ConfirmTravel/{task-uuid}
+```
+
+### POST /travels/{id}/ConfirmTravel/{taskId}
+
+Completes confirms travel task - meaning confirms (and completes) the travel request
+
+```sh
+curl -H "Content-Type: application/json" -H "Accept: application/json" -X POST http://localhost:8080/travels/{uuid}/tasks/ConfirmTravel/{task-uuid} -d '{}'
+```
diff --git a/03-kogito-travel-agency/docs/images/book-flight-process.png b/03-kogito-travel-agency/docs/images/book-flight-process.png
new file mode 100644
index 00000000000..aa2e5b968cb
Binary files /dev/null and b/03-kogito-travel-agency/docs/images/book-flight-process.png differ
diff --git a/03-kogito-travel-agency/docs/images/book-hotel-process.png b/03-kogito-travel-agency/docs/images/book-hotel-process.png
new file mode 100644
index 00000000000..d6868106144
Binary files /dev/null and b/03-kogito-travel-agency/docs/images/book-hotel-process.png differ
diff --git a/03-kogito-travel-agency/docs/images/datamodel.png b/03-kogito-travel-agency/docs/images/datamodel.png
new file mode 100644
index 00000000000..caa791101ba
Binary files /dev/null and b/03-kogito-travel-agency/docs/images/datamodel.png differ
diff --git a/03-kogito-travel-agency/docs/images/decisiontable.png b/03-kogito-travel-agency/docs/images/decisiontable.png
new file mode 100644
index 00000000000..786b40499f4
Binary files /dev/null and b/03-kogito-travel-agency/docs/images/decisiontable.png differ
diff --git a/03-kogito-travel-agency/docs/images/list-trips.png b/03-kogito-travel-agency/docs/images/list-trips.png
new file mode 100644
index 00000000000..47b43707693
Binary files /dev/null and b/03-kogito-travel-agency/docs/images/list-trips.png differ
diff --git a/03-kogito-travel-agency/docs/images/new-trip.png b/03-kogito-travel-agency/docs/images/new-trip.png
new file mode 100644
index 00000000000..1d7ef3a6e1f
Binary files /dev/null and b/03-kogito-travel-agency/docs/images/new-trip.png differ
diff --git a/03-kogito-travel-agency/docs/images/tasks.png b/03-kogito-travel-agency/docs/images/tasks.png
new file mode 100644
index 00000000000..f5c31a75e7f
Binary files /dev/null and b/03-kogito-travel-agency/docs/images/tasks.png differ
diff --git a/03-kogito-travel-agency/docs/images/travels-process.png b/03-kogito-travel-agency/docs/images/travels-process.png
new file mode 100644
index 00000000000..47d55607172
Binary files /dev/null and b/03-kogito-travel-agency/docs/images/travels-process.png differ
diff --git a/03-kogito-travel-agency/docs/images/trip-details.png b/03-kogito-travel-agency/docs/images/trip-details.png
new file mode 100644
index 00000000000..db497e1cba1
Binary files /dev/null and b/03-kogito-travel-agency/docs/images/trip-details.png differ
diff --git a/03-kogito-travel-agency/mvnw b/03-kogito-travel-agency/mvnw
new file mode 100755
index 00000000000..d2f0ea38081
--- /dev/null
+++ b/03-kogito-travel-agency/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/03-kogito-travel-agency/mvnw.cmd b/03-kogito-travel-agency/mvnw.cmd
new file mode 100644
index 00000000000..b26ab24f039
--- /dev/null
+++ b/03-kogito-travel-agency/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/03-kogito-travel-agency/pom.xml b/03-kogito-travel-agency/pom.xml
new file mode 100644
index 00000000000..136a11e6c45
--- /dev/null
+++ b/03-kogito-travel-agency/pom.xml
@@ -0,0 +1,168 @@
+
+
+ 4.0.0
+ org.acme.travels
+ kogito-travel-agency
+ 1.0-SNAPSHOT
+
+ 2.22.0
+ 1.8
+ 8.0.0-SNAPSHOT
+ 1.8
+ 999-SNAPSHOT
+ UTF-8
+ UTF-8
+
+
+
+
+ io.quarkus
+ quarkus-bom
+ ${quarkus.version}
+ pom
+ import
+
+
+
+
+
+ io.quarkus
+ quarkus-kogito
+
+
+ org.kie.kogito
+ jbpm-flow-builder
+ ${kogito.version}
+
+
+ org.kie.kogito
+ monitoring-prometheus-addon
+ ${kogito.version}
+
+
+ io.quarkus
+ quarkus-infinispan-client
+
+
+ org.kie.kogito
+ infinispan-persistence-addon
+ ${kogito.version}
+
+
+ org.kie.kogito
+ kogito-events-reactive-messaging-addon
+ ${kogito.version}
+
+
+ org.drools
+ drools-decisiontables
+ 7.22.0.Final
+
+
+ drools-core
+ org.drools
+
+
+ drools-compiler
+ org.drools
+
+
+
+
+
+ io.quarkus
+ quarkus-smallrye-reactive-messaging-kafka
+
+
+ io.quarkus
+ quarkus-kafka-client
+
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
+ io.quarkus
+ quarkus-smallrye-openapi
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+ ${quarkus.version}
+
+
+
+ build
+
+
+
+
+
+ maven-surefire-plugin
+ ${surefire-plugin.version}
+
+
+ org.jboss.logmanager.LogManager
+
+
+
+
+
+
+
+ native
+
+
+ native
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+ ${quarkus.version}
+
+
+
+ native-image
+
+
+ true
+
+
+
+
+
+ maven-failsafe-plugin
+ ${surefire-plugin.version}
+
+
+
+ integration-test
+ verify
+
+
+
+ ${project.build.directory}/${project.build.finalName}-runner
+
+
+
+
+
+
+
+
+
+
diff --git a/03-kogito-travel-agency/src/main/docker/Dockerfile.jvm b/03-kogito-travel-agency/src/main/docker/Dockerfile.jvm
new file mode 100644
index 00000000000..5a0efc6ca1c
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/docker/Dockerfile.jvm
@@ -0,0 +1,22 @@
+####
+# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
+#
+# Before building the docker image run:
+#
+# mvn package
+#
+# Then, build the image with:
+#
+# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/using-kogito-jvm .
+#
+# Then run the container using:
+#
+# docker run -i --rm -p 8080:8080 quarkus/using-kogito-jvm
+#
+###
+FROM fabric8/java-alpine-openjdk8-jre
+ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
+ENV AB_ENABLED=jmx_exporter
+COPY target/lib/* /deployments/lib/
+COPY target/*-runner.jar /deployments/app.jar
+ENTRYPOINT [ "/deployments/run-java.sh" ]
\ No newline at end of file
diff --git a/03-kogito-travel-agency/src/main/docker/Dockerfile.native b/03-kogito-travel-agency/src/main/docker/Dockerfile.native
new file mode 100644
index 00000000000..49bc0edc485
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/docker/Dockerfile.native
@@ -0,0 +1,22 @@
+####
+# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode
+#
+# Before building the docker image run:
+#
+# mvn package -Pnative -Dnative-image.docker-build=true
+#
+# Then, build the image with:
+#
+# docker build -f src/main/docker/Dockerfile.native -t quarkus/using-kogito .
+#
+# Then run the container using:
+#
+# docker run -i --rm -p 8080:8080 quarkus/using-kogito
+#
+###
+FROM registry.access.redhat.com/ubi8/ubi-minimal
+WORKDIR /work/
+COPY target/*-runner /work/application
+RUN chmod 775 /work
+EXPOSE 8080
+CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
\ No newline at end of file
diff --git a/03-kogito-travel-agency/src/main/java/org/acme/travels/Address.java b/03-kogito-travel-agency/src/main/java/org/acme/travels/Address.java
new file mode 100644
index 00000000000..68b329b5774
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/java/org/acme/travels/Address.java
@@ -0,0 +1,58 @@
+package org.acme.travels;
+
+public class Address {
+
+ private String street;
+ private String city;
+ private String zipCode;
+ private String country;
+
+ public Address() {
+
+ }
+
+ public Address(String street, String city, String zipCode, String country) {
+ super();
+ this.street = street;
+ this.city = city;
+ this.zipCode = zipCode;
+ this.country = country;
+ }
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getZipCode() {
+ return zipCode;
+ }
+
+ public void setZipCode(String zipCode) {
+ this.zipCode = zipCode;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ @Override
+ public String toString() {
+ return "Address [street=" + street + ", city=" + city + ", zipCode=" + zipCode + ", country=" + country + "]";
+ }
+}
diff --git a/03-kogito-travel-agency/src/main/java/org/acme/travels/Flight.java b/03-kogito-travel-agency/src/main/java/org/acme/travels/Flight.java
new file mode 100644
index 00000000000..53393a14d77
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/java/org/acme/travels/Flight.java
@@ -0,0 +1,69 @@
+package org.acme.travels;
+
+import java.util.Date;
+
+public class Flight {
+
+ private String flightNumber;
+ private String seat;
+ private String gate;
+ private Date departure;
+ private Date arrival;
+
+ public Flight() {
+
+ }
+
+ public Flight(String flightNumber, Date departure, Date arrival) {
+ super();
+ this.flightNumber = flightNumber;
+ this.departure = departure;
+ this.arrival = arrival;
+ }
+
+ public String getFlightNumber() {
+ return flightNumber;
+ }
+
+ public void setFlightNumber(String flightNumber) {
+ this.flightNumber = flightNumber;
+ }
+
+ public String getSeat() {
+ return seat;
+ }
+
+ public void setSeat(String seat) {
+ this.seat = seat;
+ }
+
+ public String getGate() {
+ return gate;
+ }
+
+ public void setGate(String gate) {
+ this.gate = gate;
+ }
+
+ public Date getDeparture() {
+ return departure;
+ }
+
+ public void setDeparture(Date departure) {
+ this.departure = departure;
+ }
+
+ public Date getArrival() {
+ return arrival;
+ }
+
+ public void setArrival(Date arrival) {
+ this.arrival = arrival;
+ }
+
+ @Override
+ public String toString() {
+ return "Flight [flightNumber=" + flightNumber + ", seat=" + seat + ", gate=" + gate + ", departure=" + departure
+ + ", arrival=" + arrival + "]";
+ }
+}
diff --git a/03-kogito-travel-agency/src/main/java/org/acme/travels/Hotel.java b/03-kogito-travel-agency/src/main/java/org/acme/travels/Hotel.java
new file mode 100644
index 00000000000..8e705966a5f
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/java/org/acme/travels/Hotel.java
@@ -0,0 +1,69 @@
+package org.acme.travels;
+
+public class Hotel {
+
+ private String name;
+ private Address address;
+ private String phone;
+ private String bookingNumber;
+ private String room;
+
+ public Hotel() {
+
+ }
+
+ public Hotel(String name, Address address, String phone, String bookingNumber) {
+ super();
+ this.name = name;
+ this.address = address;
+ this.phone = phone;
+ this.bookingNumber = bookingNumber;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Address getAddress() {
+ return address;
+ }
+
+ public void setAddress(Address address) {
+ this.address = address;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getBookingNumber() {
+ return bookingNumber;
+ }
+
+ public void setBookingNumber(String bookingNumber) {
+ this.bookingNumber = bookingNumber;
+ }
+
+ public String getRoom() {
+ return room;
+ }
+
+ public void setRoom(String room) {
+ this.room = room;
+ }
+
+ @Override
+ public String toString() {
+ return "Hotel [name=" + name + ", address=" + address + ", phone=" + phone + ", bookingNumber=" + bookingNumber
+ + ", room=" + room + "]";
+ }
+
+}
diff --git a/03-kogito-travel-agency/src/main/java/org/acme/travels/Traveller.java b/03-kogito-travel-agency/src/main/java/org/acme/travels/Traveller.java
new file mode 100644
index 00000000000..b4659ec2612
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/java/org/acme/travels/Traveller.java
@@ -0,0 +1,70 @@
+package org.acme.travels;
+
+public class Traveller {
+
+ private String firstName;
+ private String lastName;
+ private String email;
+ private String nationality;
+ private Address address;
+
+ public Traveller() {
+
+ }
+
+ public Traveller(String firstName, String lastName, String email, String nationality, Address address) {
+ super();
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.email = email;
+ this.nationality = nationality;
+ this.address = address;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getNationality() {
+ return nationality;
+ }
+
+ public void setNationality(String nationality) {
+ this.nationality = nationality;
+ }
+
+ public Address getAddress() {
+ return address;
+ }
+
+ public void setAddress(Address address) {
+ this.address = address;
+ }
+
+ @Override
+ public String toString() {
+ return "Traveller [firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + ", nationality="
+ + nationality + ", address=" + address + "]";
+ }
+
+}
diff --git a/03-kogito-travel-agency/src/main/java/org/acme/travels/Trip.java b/03-kogito-travel-agency/src/main/java/org/acme/travels/Trip.java
new file mode 100644
index 00000000000..7ed030fc1f7
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/java/org/acme/travels/Trip.java
@@ -0,0 +1,71 @@
+package org.acme.travels;
+
+import java.util.Date;
+
+public class Trip {
+
+ private String city;
+ private String country;
+ private Date begin;
+ private Date end;
+ private boolean visaRequired;
+
+ public Trip() {
+
+ }
+
+ public Trip(String city, String country, Date begin, Date end) {
+ super();
+ this.city = city;
+ this.country = country;
+ this.begin = begin;
+ this.end = end;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public Date getBegin() {
+ return begin;
+ }
+
+ public void setBegin(Date begin) {
+ this.begin = begin;
+ }
+
+ public Date getEnd() {
+ return end;
+ }
+
+ public void setEnd(Date end) {
+ this.end = end;
+ }
+
+ public boolean isVisaRequired() {
+ return visaRequired;
+ }
+
+ public void setVisaRequired(boolean visaRequired) {
+ this.visaRequired = visaRequired;
+ }
+
+ @Override
+ public String toString() {
+ return "Trip [city=" + city + ", country=" + country + ", begin=" + begin + ", end=" + end + ", visaRequired="
+ + visaRequired + "]";
+ }
+
+}
diff --git a/03-kogito-travel-agency/src/main/java/org/acme/travels/VisaApplication.java b/03-kogito-travel-agency/src/main/java/org/acme/travels/VisaApplication.java
new file mode 100644
index 00000000000..97507ccf6c8
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/java/org/acme/travels/VisaApplication.java
@@ -0,0 +1,89 @@
+package org.acme.travels;
+
+public class VisaApplication {
+
+ private String firstName;
+ private String lastName;
+ private String city;
+ private String country;
+ private int duration;
+ private String passportNumber;
+ private String nationality;
+
+ public VisaApplication() {
+
+ }
+
+ public VisaApplication(String firstName, String lastName, String city, String country, int duration,
+ String passportNumber) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.city = city;
+ this.country = country;
+ this.duration = duration;
+ this.passportNumber = passportNumber;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public int getDuration() {
+ return duration;
+ }
+
+ public void setDuration(int duration) {
+ this.duration = duration;
+ }
+
+ public String getPassportNumber() {
+ return passportNumber;
+ }
+
+ public void setPassportNumber(String passportNumber) {
+ this.passportNumber = passportNumber;
+ }
+
+ public String getNationality() {
+ return nationality;
+ }
+
+ public void setNationality(String nationality) {
+ this.nationality = nationality;
+ }
+
+ @Override
+ public String toString() {
+ return "VisaApplication [firstName=" + firstName + ", lastName=" + lastName + ", city=" + city + ", country="
+ + country + ", duration=" + duration + ", passportNumber=" + passportNumber + "]";
+ }
+
+}
diff --git a/03-kogito-travel-agency/src/main/java/org/acme/travels/json/VisaApplicationJsonbSerializer.java b/03-kogito-travel-agency/src/main/java/org/acme/travels/json/VisaApplicationJsonbSerializer.java
new file mode 100644
index 00000000000..ca6feb5eb96
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/java/org/acme/travels/json/VisaApplicationJsonbSerializer.java
@@ -0,0 +1,11 @@
+package org.acme.travels.json;
+
+import org.acme.travels.VisaApplication;
+
+import io.quarkus.kafka.client.serialization.JsonbSerializer;
+import io.quarkus.runtime.annotations.RegisterForReflection;
+
+@RegisterForReflection
+public class VisaApplicationJsonbSerializer extends JsonbSerializer {
+
+}
diff --git a/03-kogito-travel-agency/src/main/java/org/acme/travels/service/FlightBookingService.java b/03-kogito-travel-agency/src/main/java/org/acme/travels/service/FlightBookingService.java
new file mode 100644
index 00000000000..c8d7328533c
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/java/org/acme/travels/service/FlightBookingService.java
@@ -0,0 +1,14 @@
+package org.acme.travels.service;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import org.acme.travels.Flight;
+import org.acme.travels.Trip;
+
+@ApplicationScoped
+public class FlightBookingService {
+
+ public Flight bookFlight(Trip trip) {
+ return new Flight("MX555", trip.getBegin(), trip.getEnd());
+ }
+}
diff --git a/03-kogito-travel-agency/src/main/java/org/acme/travels/service/HotelBookingService.java b/03-kogito-travel-agency/src/main/java/org/acme/travels/service/HotelBookingService.java
new file mode 100644
index 00000000000..5d85123ab67
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/java/org/acme/travels/service/HotelBookingService.java
@@ -0,0 +1,15 @@
+package org.acme.travels.service;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import org.acme.travels.Address;
+import org.acme.travels.Hotel;
+import org.acme.travels.Trip;
+
+@ApplicationScoped
+public class HotelBookingService {
+
+ public Hotel bookHotel(Trip trip) {
+ return new Hotel("Perfect hotel", new Address("street", trip.getCity(), "12345", trip.getCountry()), "09876543", "XX-012345");
+ }
+}
diff --git a/03-kogito-travel-agency/src/main/java/org/kie/kogito/app/ProcessEventListenerConfig.java b/03-kogito-travel-agency/src/main/java/org/kie/kogito/app/ProcessEventListenerConfig.java
new file mode 100644
index 00000000000..6897c00e84d
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/java/org/kie/kogito/app/ProcessEventListenerConfig.java
@@ -0,0 +1,14 @@
+package org.kie.kogito.app;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import org.kie.addons.monitoring.process.PrometheusProcessEventListener;
+import org.kie.kogito.process.impl.DefaultProcessEventListenerConfig;
+
+@ApplicationScoped
+public class ProcessEventListenerConfig extends DefaultProcessEventListenerConfig {
+
+ public ProcessEventListenerConfig() {
+ super(new PrometheusProcessEventListener("acme-travels"));
+ }
+}
diff --git a/03-kogito-travel-agency/src/main/java/org/kie/kogito/app/RuleEventListenerConfig.java b/03-kogito-travel-agency/src/main/java/org/kie/kogito/app/RuleEventListenerConfig.java
new file mode 100644
index 00000000000..8ddf512fb61
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/java/org/kie/kogito/app/RuleEventListenerConfig.java
@@ -0,0 +1,15 @@
+package org.kie.kogito.app;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import org.drools.core.config.DefaultRuleEventListenerConfig;
+import org.kie.addons.monitoring.rule.PrometheusMetricsDroolsListener;
+
+@ApplicationScoped
+public class RuleEventListenerConfig extends DefaultRuleEventListenerConfig {
+
+
+ public RuleEventListenerConfig() {
+ super(new PrometheusMetricsDroolsListener("acme-travels"));
+ }
+}
diff --git a/03-kogito-travel-agency/src/main/resources/META-INF/resources/index.html b/03-kogito-travel-agency/src/main/resources/META-INF/resources/index.html
new file mode 100644
index 00000000000..ecf6b4ea4b3
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/resources/META-INF/resources/index.html
@@ -0,0 +1,614 @@
+
+
+
+
+ Kogito Travel Agency
+
+
+
+
+
+
+
+
+
+
+
Kogito Travel Agency
+
+
Plan your next trip with Kogito Travel Agency, it's easy and fast!
+
+
+
+
+
Travels
+
+
+
+
+
Traveller name
+
Destination
+
Dates
+
Visa required
+
Hotel
+
Flight
+
Actions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Plan new trip
+
+
+
+
+
Traveller
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Trip
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Details of a travel
+
+
+
+
+
+
+
+
Traveller
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Trip
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Hotel
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Flight
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Details of a travel
+
+
+
+
+
+
+
Tasks
+
+
+
+
Task name
+
Actions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Visa application
+
+
+
+
+
+
+
+
Visa application
+
+
+
+
Traveller
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Trip
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Visa details
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/03-kogito-travel-agency/src/main/resources/application.properties b/03-kogito-travel-agency/src/main/resources/application.properties
new file mode 100644
index 00000000000..f9be96c1e71
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/resources/application.properties
@@ -0,0 +1,11 @@
+# Configuration file
+# key = value
+quarkus.infinispan-client.server-list=localhost:11222
+
+mp.messaging.outgoing.visaapplications.connector=smallrye-kafka
+mp.messaging.outgoing.visaapplications.topic=visaapplications
+mp.messaging.outgoing.visaapplications.value.serializer=org.acme.travels.json.VisaApplicationJsonbSerializer
+
+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
\ No newline at end of file
diff --git a/03-kogito-travel-agency/src/main/resources/org/acme/travels/flightBooking.bpmn2 b/03-kogito-travel-agency/src/main/resources/org/acme/travels/flightBooking.bpmn2
new file mode 100644
index 00000000000..b324eb47903
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/resources/org/acme/travels/flightBooking.bpmn2
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+ Message_1
+ Message_2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SequenceFlow_2
+
+
+
+
+
+
+
+ SequenceFlow_2
+ SequenceFlow_1
+
+
+
+
+ DataInput_1
+
+
+ DataOutput_1
+
+
+
+ trip
+ DataInput_1
+
+
+ DataOutput_1
+ flight
+
+
+
+
+
+
+
+
+ SequenceFlow_1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/03-kogito-travel-agency/src/main/resources/org/acme/travels/hotelBooking.bpmn2 b/03-kogito-travel-agency/src/main/resources/org/acme/travels/hotelBooking.bpmn2
new file mode 100644
index 00000000000..c6b013329dd
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/resources/org/acme/travels/hotelBooking.bpmn2
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Message_1
+ Message_2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SequenceFlow_2
+
+
+
+
+
+
+
+ SequenceFlow_2
+ SequenceFlow_1
+
+
+
+
+ DataInput_1
+
+
+ DataOutput_1
+
+
+
+ trip
+ DataInput_1
+
+
+ DataOutput_1
+ hotel
+
+
+
+
+
+
+
+
+ SequenceFlow_1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/03-kogito-travel-agency/src/main/resources/org/acme/travels/travels.bpmn2 b/03-kogito-travel-agency/src/main/resources/org/acme/travels/travels.bpmn2
new file mode 100644
index 00000000000..195e19cd953
--- /dev/null
+++ b/03-kogito-travel-agency/src/main/resources/org/acme/travels/travels.bpmn2
@@ -0,0 +1,549 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SequenceFlow_1
+
+
+
+
+
+
+
+ SequenceFlow_1
+ SequenceFlow_2
+
+
+
+
+
+ DataInput_19
+ DataInput_20
+
+
+ DataOutput_1
+
+
+
+ traveller
+ DataInput_19
+
+
+ trip
+ DataInput_20
+
+
+ DataOutput_1
+ trip
+
+
+
+ SequenceFlow_2
+ SequenceFlow_3
+ SequenceFlow_4
+
+
+
+
+
+
+
+ SequenceFlow_3
+ SequenceFlow_13
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataInput_1
+ DataInput_2
+ DataInput_3
+ DataInput_4
+ DataInput_5
+ DataInput_6
+ DataInput_7
+ DataInput_8
+ DataInput_9
+ DataInput_21
+ DataInput_22
+
+
+ DataOutput_4
+
+
+
+ DataInput_1
+
+ VisaApplication
+ DataInput_1
+
+
+
+ DataInput_2
+
+ 1
+ DataInput_2
+
+
+
+ DataInput_3
+
+
+ DataInput_4
+
+
+ DataInput_5
+
+
+ DataInput_6
+
+ true
+ DataInput_6
+
+
+
+ DataInput_7
+
+
+ DataInput_8
+
+ en-UK
+ DataInput_8
+
+
+
+ DataInput_9
+
+
+ trip
+ DataInput_21
+
+
+ traveller
+ DataInput_22
+
+
+ DataOutput_4
+ visaApplication
+
+
+
+ SequenceFlow_4
+ SequenceFlow_15
+ SequenceFlow_6
+
+
+
+
+ return trip.isVisaRequired();
+
+
+ return !trip.isVisaRequired();
+
+
+ SequenceFlow_6
+ SequenceFlow_7
+ SequenceFlow_8
+
+
+
+
+
+
+
+
+ SequenceFlow_7
+ SequenceFlow_10
+
+
+
+
+
+ DataInput_23
+ DataInput_24
+
+
+ DataOutput_2
+
+
+
+ traveller
+ DataInput_23
+
+
+ trip
+ DataInput_24
+
+
+ DataOutput_2
+ hotel
+
+
+
+
+
+
+
+
+ SequenceFlow_8
+ SequenceFlow_9
+
+
+
+
+
+ DataInput_25
+ DataInput_26
+
+
+ DataOutput_3
+
+
+
+ traveller
+ DataInput_25
+
+
+ trip
+ DataInput_26
+
+
+ DataOutput_3
+ flight
+
+
+
+
+
+ SequenceFlow_9
+ SequenceFlow_10
+ SequenceFlow_11
+
+
+
+
+
+
+
+
+
+ SequenceFlow_11
+ SequenceFlow_12
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataInput_10
+ DataInput_11
+ DataInput_12
+ DataInput_13
+ DataInput_14
+ DataInput_15
+ DataInput_16
+ DataInput_17
+ DataInput_18
+ DataInput_27
+ DataInput_28
+
+
+
+
+ DataInput_10
+
+ ConfirmTravel
+ DataInput_10
+
+
+
+ DataInput_11
+
+ 1
+ DataInput_11
+
+
+
+ DataInput_12
+
+
+ DataInput_13
+
+
+ DataInput_14
+
+
+ DataInput_15
+
+ true
+ DataInput_15
+
+
+
+ DataInput_16
+
+
+ DataInput_17
+
+ en-UK
+ DataInput_17
+
+
+
+ DataInput_18
+
+
+ flight
+ DataInput_27
+
+
+ hotel
+ DataInput_28
+
+
+
+
+
+
+
+
+
+ SequenceFlow_12
+
+
+
+ SequenceFlow_13
+ SequenceFlow_14
+ SequenceFlow_15
+
+
+
+
+
+
+
+
+ SequenceFlow_14
+
+
+ visaApplication
+ DataInput_29
+
+
+ DataInput_29
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/03-kogito-travel-agency/src/main/resources/org/acme/travels/visa-rules.xls b/03-kogito-travel-agency/src/main/resources/org/acme/travels/visa-rules.xls
new file mode 100644
index 00000000000..d13e1103bcb
Binary files /dev/null and b/03-kogito-travel-agency/src/main/resources/org/acme/travels/visa-rules.xls differ
diff --git a/03-kogito-travel-agency/src/test/java/org/acme/travel/BookFlightTest.java b/03-kogito-travel-agency/src/test/java/org/acme/travel/BookFlightTest.java
new file mode 100644
index 00000000000..5cb3aba8d5d
--- /dev/null
+++ b/03-kogito-travel-agency/src/test/java/org/acme/travel/BookFlightTest.java
@@ -0,0 +1,57 @@
+package org.acme.travel;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.acme.travels.Address;
+import org.acme.travels.Flight;
+import org.acme.travels.Traveller;
+import org.acme.travels.Trip;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.kie.kogito.Model;
+import org.kie.kogito.process.Process;
+import org.kie.kogito.process.ProcessInstance;
+
+import io.quarkus.test.junit.QuarkusTest;
+
+@Disabled("Disabled by default as it requires inifinispan and kafka")
+@QuarkusTest
+public class BookFlightTest {
+
+ @Inject
+ @Named("flightBooking")
+ Process extends Model> bookFlightProcess;
+
+ @Test
+ public void testBookingFlight() {
+
+ assertNotNull(bookFlightProcess);
+
+ Model m = bookFlightProcess.createModel();
+ Map parameters = new HashMap<>();
+ parameters.put("traveller", new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US")));
+ parameters.put("trip", new Trip("New York", "US", new Date(), new Date()));
+
+ m.fromMap(parameters);
+
+ ProcessInstance> processInstance = bookFlightProcess.createInstance(m);
+ processInstance.start();
+ assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status());
+
+ Model result = (Model)processInstance.variables();
+ assertEquals(3, result.toMap().size());
+ Flight flight = (Flight) result.toMap().get("flight");
+ assertNotNull(flight);
+ assertEquals("MX555", flight.getFlightNumber());
+ assertNotNull(flight.getArrival());
+ assertNotNull(flight.getDeparture());
+ }
+}
diff --git a/03-kogito-travel-agency/src/test/java/org/acme/travel/BookHotelTest.java b/03-kogito-travel-agency/src/test/java/org/acme/travel/BookHotelTest.java
new file mode 100644
index 00000000000..33dabae04b7
--- /dev/null
+++ b/03-kogito-travel-agency/src/test/java/org/acme/travel/BookHotelTest.java
@@ -0,0 +1,57 @@
+package org.acme.travel;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.acme.travels.Address;
+import org.acme.travels.Hotel;
+import org.acme.travels.Traveller;
+import org.acme.travels.Trip;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.kie.kogito.Model;
+import org.kie.kogito.process.Process;
+import org.kie.kogito.process.ProcessInstance;
+
+import io.quarkus.test.junit.QuarkusTest;
+
+@Disabled("Disabled by default as it requires inifinispan and kafka")
+@QuarkusTest
+public class BookHotelTest {
+
+ @Inject
+ @Named("hotelBooking")
+ Process extends Model> bookHotelProcess;
+
+ @Test
+ public void testBookingHotel() {
+
+ assertNotNull(bookHotelProcess);
+
+ Model m = bookHotelProcess.createModel();
+ Map parameters = new HashMap<>();
+ parameters.put("traveller", new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US")));
+ parameters.put("trip", new Trip("New York", "US", new Date(), new Date()));
+
+ m.fromMap(parameters);
+
+ ProcessInstance> processInstance = bookHotelProcess.createInstance(m);
+ processInstance.start();
+ assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status());
+
+ Model result = (Model)processInstance.variables();
+ assertEquals(3, result.toMap().size());
+ Hotel hotel = (Hotel) result.toMap().get("hotel");
+ assertNotNull(hotel);
+ assertEquals("Perfect hotel", hotel.getName());
+ assertEquals("XX-012345", hotel.getBookingNumber());
+ assertEquals("09876543", hotel.getPhone());
+ }
+}
diff --git a/03-kogito-travel-agency/src/test/java/org/acme/travel/TravelTest.java b/03-kogito-travel-agency/src/test/java/org/acme/travel/TravelTest.java
new file mode 100644
index 00000000000..af94c4c1971
--- /dev/null
+++ b/03-kogito-travel-agency/src/test/java/org/acme/travel/TravelTest.java
@@ -0,0 +1,125 @@
+package org.acme.travel;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.acme.travels.Address;
+import org.acme.travels.Flight;
+import org.acme.travels.Hotel;
+import org.acme.travels.Traveller;
+import org.acme.travels.Trip;
+import org.acme.travels.VisaApplication;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.kie.kogito.Model;
+import org.kie.kogito.process.Process;
+import org.kie.kogito.process.ProcessInstance;
+import org.kie.kogito.process.WorkItem;
+
+import io.quarkus.test.junit.QuarkusTest;
+
+@Disabled("Disabled by default as it requires inifinispan and kafka")
+@QuarkusTest
+public class TravelTest {
+
+ @Inject
+ @Named("travels")
+ Process extends Model> travelsProcess;
+
+ @Test
+ public void testTravelNoVisaRequired() {
+
+ assertNotNull(travelsProcess);
+
+ Model m = travelsProcess.createModel();
+ Map parameters = new HashMap<>();
+ parameters.put("traveller", new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US")));
+ parameters.put("trip", new Trip("New York", "US", new Date(), new Date()));
+
+ m.fromMap(parameters);
+
+ ProcessInstance> processInstance = travelsProcess.createInstance(m);
+ processInstance.start();
+ assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_ACTIVE, processInstance.status());
+
+ Model result = (Model)processInstance.variables();
+ assertEquals(5, result.toMap().size());
+ Hotel hotel = (Hotel) result.toMap().get("hotel");
+ assertNotNull(hotel);
+ assertEquals("Perfect hotel", hotel.getName());
+ assertEquals("XX-012345", hotel.getBookingNumber());
+ assertEquals("09876543", hotel.getPhone());
+
+ Flight flight = (Flight) result.toMap().get("flight");
+ assertNotNull(flight);
+ assertEquals("MX555", flight.getFlightNumber());
+ assertNotNull(flight.getArrival());
+ assertNotNull(flight.getDeparture());
+
+ List workItems = processInstance.workItems();
+ assertEquals(1, workItems.size());
+ assertEquals("ConfirmTravel", workItems.get(0).getName());
+
+ processInstance.completeWorkItem(workItems.get(0).getId(), null);
+
+ assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status());
+ }
+
+ @Test
+ public void testTravelVisaRequired() {
+
+ assertNotNull(travelsProcess);
+
+ Model m = travelsProcess.createModel();
+ Map parameters = new HashMap<>();
+ parameters.put("traveller", new Traveller("Jan", "Kowalski", "jan.kowalski@example.com", "Polish", new Address("polna", "Krakow", "32000", "Poland")));
+ parameters.put("trip", new Trip("New York", "US", new Date(), new Date()));
+
+ m.fromMap(parameters);
+
+ ProcessInstance> processInstance = travelsProcess.createInstance(m);
+ processInstance.start();
+ assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_ACTIVE, processInstance.status());
+
+ List workItems = processInstance.workItems();
+ assertEquals(1, workItems.size());
+ assertEquals("VisaApplication", workItems.get(0).getName());
+
+ Map results = new HashMap<>();
+ results.put("visaApplication", new VisaApplication("Jan", "Kowalski", "New York", "US", 10, "XXX098765"));
+
+ processInstance.completeWorkItem(workItems.get(0).getId(), results);
+
+ assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_ACTIVE, processInstance.status());
+
+ Model result = (Model)processInstance.variables();
+ assertEquals(5, result.toMap().size());
+ Hotel hotel = (Hotel) result.toMap().get("hotel");
+ assertNotNull(hotel);
+ assertEquals("Perfect hotel", hotel.getName());
+ assertEquals("XX-012345", hotel.getBookingNumber());
+ assertEquals("09876543", hotel.getPhone());
+
+ Flight flight = (Flight) result.toMap().get("flight");
+ assertNotNull(flight);
+ assertEquals("MX555", flight.getFlightNumber());
+ assertNotNull(flight.getArrival());
+ assertNotNull(flight.getDeparture());
+
+ workItems = processInstance.workItems();
+ assertEquals(1, workItems.size());
+ assertEquals("ConfirmTravel", workItems.get(0).getName());
+
+ processInstance.completeWorkItem(workItems.get(0).getId(), null);
+
+ assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status());
+ }
+}
diff --git a/03-kogito-travel-agency/src/test/java/org/acme/travel/VisaRulesTest.java b/03-kogito-travel-agency/src/test/java/org/acme/travel/VisaRulesTest.java
new file mode 100644
index 00000000000..437c7f7aab3
--- /dev/null
+++ b/03-kogito-travel-agency/src/test/java/org/acme/travel/VisaRulesTest.java
@@ -0,0 +1,67 @@
+package org.acme.travel;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Date;
+
+import javax.inject.Inject;
+
+import org.acme.travels.Address;
+import org.acme.travels.Traveller;
+import org.acme.travels.Trip;
+import org.drools.core.common.InternalAgenda;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.kie.api.runtime.KieSession;
+import org.kie.kogito.rules.KieRuntimeBuilder;
+
+import io.quarkus.test.junit.QuarkusTest;
+
+@Disabled("Disabled by default as it requires inifinispan and kafka")
+@QuarkusTest
+public class VisaRulesTest {
+
+
+ @Inject
+ KieRuntimeBuilder ruleRuntime;
+
+ @Test
+ public void testVisaNotRequiredRule() {
+
+ assertNotNull(ruleRuntime);
+
+ Traveller traveller = new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US"));
+ Trip trip = new Trip("New York", "US", new Date(), new Date());
+
+ KieSession ksession = ruleRuntime.newKieSession();
+ ((InternalAgenda) ksession.getAgenda()).activateRuleFlowGroup("visas");
+ ksession.insert(trip);
+ ksession.insert(traveller);
+ ksession.fireAllRules();
+
+ ksession.dispose();
+
+ assertFalse(trip.isVisaRequired());
+ }
+
+ @Test
+ public void testVisaRequiredRule() {
+
+ assertNotNull(ruleRuntime);
+
+ Traveller traveller = new Traveller("Jan", "Kowalski", "jan.kowalski@example.com", "Polish", new Address("polna", "Krakow", "32000", "Poland"));
+ Trip trip = new Trip("New York", "US", new Date(), new Date());
+
+ KieSession ksession = ruleRuntime.newKieSession();
+ ((InternalAgenda) ksession.getAgenda()).activateRuleFlowGroup("visas");
+ ksession.insert(trip);
+ ksession.insert(traveller);
+ ksession.fireAllRules();
+
+ ksession.dispose();
+
+ assertTrue(trip.isVisaRequired());
+ }
+}
diff --git a/03-kogito-visas/.gitignore b/03-kogito-visas/.gitignore
new file mode 100644
index 00000000000..dc611a28acb
--- /dev/null
+++ b/03-kogito-visas/.gitignore
@@ -0,0 +1,18 @@
+bin/
+/target
+/local
+
+# Eclipse, Netbeans and IntelliJ files
+/.*
+!.gitignore
+/nbproject
+/*.ipr
+/*.iws
+/*.iml
+
+# Repository wide ignore mac DS_Store files
+.DS_Store
+*~
+/settings*.xml
+*.db
+*.tlog
diff --git a/03-kogito-visas/README.md b/03-kogito-visas/README.md
new file mode 100644
index 00000000000..403c855b38a
--- /dev/null
+++ b/03-kogito-visas/README.md
@@ -0,0 +1,203 @@
+# Kogito Visas
+
+
+NOTE: This requires Kogito 0.3.0 that is not yet released and that's why it refers to snapshot versions
+for both Kogito and Quarkus
+
+## Description
+
+This is another service of the Kogito Travel Agency application. It's responsible for processing visa applications
+that are sent during travel requests.
+
+In it's current state it simply accepts incoming visa applications from Kafka topic and process them
+
+* automatically if the rules match the visa application details
+* manually otherwise
+
+Response is logged into the visa application and the processing ends. Further evolutions of the service
+will add additional hanlding to the approved or rejected visa applications.
+
+## Activities to perform
+
+* Create project using Quarkus Maven plugin with following extensions
+ * Kogito
+ * OpenApi
+* Import project into Eclipse IDE - requires BPMN modeller plugin installed
+* Create data model
+ * VisaApplication
+* Create decision logic
+ * Visa approvals
+* Create business logic
+ * Public business process to deal with visa applications
+* Configure messaging and events
+* Create or import UI components
+* Add custom metrics based on the approved and rejected visa applications
+* Create dashboard based on metrics
+
+## Data model
+
+Kogito Travel Agency booking system will be based on following data model
+
+**Visa Application**
+
+A basic visa application information required to process
+
+
+## Decision logic
+
+The decision logic will be implemented as a set of rules in DRL format. These rules will be responsible for automatic visa application approval
+
+
+## Business logic
+
+Business logic will be based on business processes
+
+Public process that will be responsible for processing visa application
+
+
+
+
+# Try out the complete service
+
+## Installing and Running
+
+### Prerequisites
+
+You will need:
+ - Java 1.8.0+ installed
+ - Environment variable JAVA_HOME set accordingly
+ - Maven 3.5.4+ installed
+
+When using native image compilation, you will also need:
+ - GraalVM installed
+ - Environment variable GRAALVM_HOME set accordingly
+ - Note that GraalVM native image compilation typically requires other packages (glibc-devel, zlib-devel and gcc) to be installed too, please refer to GraalVM installation documentation for more details.
+
+### Infrastructure requirements
+
+#### Infinispan
+
+This application requires an Inifinispan server to be available and by default expects it to be on default port and localhost.
+
+You can install Inifinispan server by downloading it from [https://infinispan.org/download/](official website) version to be used in 10.0.0.Beta4
+
+
+#### Apache Kafka
+
+This application requires a Apache Kafka installed and following topics created
+
+* `visaapplications` - used to send visa application that are consumed and processed by Kogito Visas service
+* `kogito-processinstances-events` - used to emit events by kogito that can be consumed by data index service and other services
+
+
+### Compile and Run in Local Dev Mode
+
+```
+mvn clean package quarkus:dev
+```
+
+NOTE: With dev mode of Quarkus you can take advantage of hot reload for business assets like processes, rules and decision
+tables and java code. No need to redeploy or restart your running application.During this workshop we will create a software system for a startup travel agency called Kogito Travel Agency. The first iteration of the system will consist of a set of services that are able to deal with travel requests and the booking of hotels and flights.
+
+
+### Compile and Run using Local Native Image
+Note that this requires GRAALVM_HOME to point to a valid GraalVM installation
+
+```
+mvn clean package -Pnative
+```
+
+To run the generated native executable, generated in `target/`, execute
+
+```
+./target/kogito-visas-{version}-runner
+```
+
+## Known issues
+
+
+## User interface
+
+Kogito Visas comes with basic UI that allows to
+
+
+### list currently opened visa applications
+
+
+
+
+### approve/reject selected visa application
+
+
+
+To start Kogito Travel Agency UI just point your browser to [http://localhost:8090](http://localhost:8090)
+
+## REST API
+
+Once the service is up and running, you can use the following examples to interact with the service.
+
+
+### GET /visaApplications
+
+Returns list of travel requests currently active:
+
+```sh
+curl -X GET http://localhost:8090/visaApplications
+```
+
+As response an array of travels is returned.
+
+### GET /visaApplications/{id}
+
+Returns travel request with given id (if active):
+
+```sh
+curl -X GET http://localhost:8090/visaApplications/{uuid}
+```
+
+As response a single travel request is returned if found, otherwise no content (204) is returned.
+
+### DELETE /visaApplications/{id}
+
+Cancels travel request with given id
+
+```sh
+curl -X DELETE http://localhost:8090/visaApplications/{uuid}
+```
+
+### GET /visaApplications/{id}/tasks
+
+Returns currently assigned user tasks for give travel request:
+
+```sh
+curl -X GET http://localhost:8090/visaApplications/{uuid}/tasks
+```
+
+### GET /visaApplications/{id}/ApplicationApproval/{taskId}
+
+Returns visa application task information:
+
+```sh
+curl -X GET http://localhost:8090/visaApplications/{uuid}/ApplicationApproval/{task-uuid}
+```
+
+### POST /visaApplications/{id}/ApplicationApproval/{taskId}
+
+Completes visa application task
+
+```sh
+curl -H "Content-Type: application/json" -H "Accept: application/json" -X POST http://localhost:8090/visaApplications/435aa429-5ddb-4480-9219-ad9c51bbf885/ApplicationApproval/98796868-d94e-4363-8e8f-6a1d31cbbff6 -d @- << EOF
+{
+ "application" : {
+ "firstName" : "Jan",
+ "lastName" : "Kowalski",
+ "nationality" : "Polish",
+ "city" : "New York",
+ "country" : "US",
+ "passportNumber" : "ABC09876",
+ "duration" : 25,
+ "approved" : true
+ }
+}
+EOF
+```
diff --git a/03-kogito-visas/docs/images/approve-reject-visas.png b/03-kogito-visas/docs/images/approve-reject-visas.png
new file mode 100644
index 00000000000..0b24e30f2a5
Binary files /dev/null and b/03-kogito-visas/docs/images/approve-reject-visas.png differ
diff --git a/03-kogito-visas/docs/images/list-visas.png b/03-kogito-visas/docs/images/list-visas.png
new file mode 100644
index 00000000000..71e29cb44f8
Binary files /dev/null and b/03-kogito-visas/docs/images/list-visas.png differ
diff --git a/03-kogito-visas/docs/images/visa-applications-process.png b/03-kogito-visas/docs/images/visa-applications-process.png
new file mode 100644
index 00000000000..c690aa0b549
Binary files /dev/null and b/03-kogito-visas/docs/images/visa-applications-process.png differ
diff --git a/03-kogito-visas/mvnw b/03-kogito-visas/mvnw
new file mode 100755
index 00000000000..d2f0ea38081
--- /dev/null
+++ b/03-kogito-visas/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/03-kogito-visas/mvnw.cmd b/03-kogito-visas/mvnw.cmd
new file mode 100644
index 00000000000..b26ab24f039
--- /dev/null
+++ b/03-kogito-visas/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/03-kogito-visas/pom.xml b/03-kogito-visas/pom.xml
new file mode 100644
index 00000000000..a645bf0b4a2
--- /dev/null
+++ b/03-kogito-visas/pom.xml
@@ -0,0 +1,146 @@
+
+
+ 4.0.0
+ org.acme.travels
+ kogito-visas
+ 1.0-SNAPSHOT
+
+ 2.22.0
+ 1.8
+ 8.0.0-SNAPSHOT
+ 1.8
+ 999-SNAPSHOT
+ UTF-8
+ UTF-8
+
+
+
+
+ io.quarkus
+ quarkus-bom
+ ${quarkus.version}
+ pom
+ import
+
+
+
+
+
+ io.quarkus
+ quarkus-resteasy
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
+ io.quarkus
+ quarkus-kogito
+
+
+ io.quarkus
+ quarkus-smallrye-reactive-messaging-kafka
+
+
+ io.quarkus
+ quarkus-kafka-client
+
+
+ org.kie.kogito
+ monitoring-prometheus-addon
+ ${kogito.version}
+
+
+ io.quarkus
+ quarkus-infinispan-client
+
+
+ org.kie.kogito
+ infinispan-persistence-addon
+ ${kogito.version}
+
+
+ org.kie.kogito
+ kogito-events-reactive-messaging-addon
+ ${kogito.version}
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+ ${quarkus.version}
+
+
+
+ build
+
+
+
+
+
+ maven-surefire-plugin
+ ${surefire-plugin.version}
+
+
+ org.jboss.logmanager.LogManager
+
+
+
+
+
+
+
+ native
+
+
+ native
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+ ${quarkus.version}
+
+
+
+ native-image
+
+
+ true
+
+
+
+
+
+ maven-failsafe-plugin
+ ${surefire-plugin.version}
+
+
+
+ integration-test
+ verify
+
+
+
+ ${project.build.directory}/${project.build.finalName}-runner
+
+
+
+
+
+
+
+
+
+
diff --git a/03-kogito-visas/src/main/docker/Dockerfile.jvm b/03-kogito-visas/src/main/docker/Dockerfile.jvm
new file mode 100644
index 00000000000..00027955dff
--- /dev/null
+++ b/03-kogito-visas/src/main/docker/Dockerfile.jvm
@@ -0,0 +1,22 @@
+####
+# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
+#
+# Before building the docker image run:
+#
+# mvn package
+#
+# Then, build the image with:
+#
+# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/sample-kogito-jvm .
+#
+# Then run the container using:
+#
+# docker run -i --rm -p 8080:8080 quarkus/sample-kogito-jvm
+#
+###
+FROM fabric8/java-alpine-openjdk8-jre
+ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
+ENV AB_ENABLED=jmx_exporter
+COPY target/lib/* /deployments/lib/
+COPY target/*-runner.jar /deployments/app.jar
+ENTRYPOINT [ "/deployments/run-java.sh" ]
\ No newline at end of file
diff --git a/03-kogito-visas/src/main/docker/Dockerfile.native b/03-kogito-visas/src/main/docker/Dockerfile.native
new file mode 100644
index 00000000000..dafe4e4bcdb
--- /dev/null
+++ b/03-kogito-visas/src/main/docker/Dockerfile.native
@@ -0,0 +1,22 @@
+####
+# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode
+#
+# Before building the docker image run:
+#
+# mvn package -Pnative -Dnative-image.docker-build=true
+#
+# Then, build the image with:
+#
+# docker build -f src/main/docker/Dockerfile.native -t quarkus/sample-kogito .
+#
+# Then run the container using:
+#
+# docker run -i --rm -p 8080:8080 quarkus/sample-kogito
+#
+###
+FROM registry.access.redhat.com/ubi8/ubi-minimal
+WORKDIR /work/
+COPY target/*-runner /work/application
+RUN chmod 775 /work
+EXPOSE 8080
+CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
\ No newline at end of file
diff --git a/03-kogito-visas/src/main/java/org/acme/travels/VisaApplication.java b/03-kogito-visas/src/main/java/org/acme/travels/VisaApplication.java
new file mode 100644
index 00000000000..41f4ea38e34
--- /dev/null
+++ b/03-kogito-visas/src/main/java/org/acme/travels/VisaApplication.java
@@ -0,0 +1,100 @@
+package org.acme.travels;
+
+public class VisaApplication {
+
+ private String firstName;
+ private String lastName;
+ private String city;
+ private String country;
+ private int duration;
+ private String passportNumber;
+ private String nationality;
+
+ private boolean approved;
+
+ public VisaApplication() {
+
+ }
+
+ public VisaApplication(String firstName, String lastName, String city, String country, int duration,
+ String passportNumber) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.city = city;
+ this.country = country;
+ this.duration = duration;
+ this.passportNumber = passportNumber;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public int getDuration() {
+ return duration;
+ }
+
+ public void setDuration(int duration) {
+ this.duration = duration;
+ }
+
+ public String getPassportNumber() {
+ return passportNumber;
+ }
+
+ public void setPassportNumber(String passportNumber) {
+ this.passportNumber = passportNumber;
+ }
+
+ public String getNationality() {
+ return nationality;
+ }
+
+ public void setNationality(String nationality) {
+ this.nationality = nationality;
+ }
+
+ public boolean isApproved() {
+ return approved;
+ }
+
+ public void setApproved(boolean approved) {
+ this.approved = approved;
+ }
+
+ @Override
+ public String toString() {
+ return "VisaApplication [firstName=" + firstName + ", lastName=" + lastName + ", city=" + city + ", country="
+ + country + ", duration=" + duration + ", passportNumber=" + passportNumber + ", approved=" + approved
+ + "]";
+ }
+
+}
diff --git a/03-kogito-visas/src/main/java/org/acme/travels/json/VisaApplicationJsonbDeserializer.java b/03-kogito-visas/src/main/java/org/acme/travels/json/VisaApplicationJsonbDeserializer.java
new file mode 100644
index 00000000000..28d7b961a8e
--- /dev/null
+++ b/03-kogito-visas/src/main/java/org/acme/travels/json/VisaApplicationJsonbDeserializer.java
@@ -0,0 +1,15 @@
+package org.acme.travels.json;
+
+import org.acme.travels.VisaApplication;
+
+import io.quarkus.kafka.client.serialization.JsonbDeserializer;
+import io.quarkus.runtime.annotations.RegisterForReflection;
+
+@RegisterForReflection
+public class VisaApplicationJsonbDeserializer extends JsonbDeserializer {
+
+ public VisaApplicationJsonbDeserializer() {
+ super(VisaApplication.class);
+ }
+
+}
diff --git a/03-kogito-visas/src/main/java/org/kie/kogito/app/ProcessEventListenerConfig.java b/03-kogito-visas/src/main/java/org/kie/kogito/app/ProcessEventListenerConfig.java
new file mode 100644
index 00000000000..18fe8218857
--- /dev/null
+++ b/03-kogito-visas/src/main/java/org/kie/kogito/app/ProcessEventListenerConfig.java
@@ -0,0 +1,28 @@
+package org.kie.kogito.app;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.enterprise.context.ApplicationScoped;
+
+import org.kie.kogito.process.impl.DefaultProcessEventListenerConfig;
+
+@ApplicationScoped
+public class ProcessEventListenerConfig extends DefaultProcessEventListenerConfig {
+
+ private VisaApplicationPrometheusProcessEventListener listener;
+ public ProcessEventListenerConfig() {
+ super();
+ }
+
+ @PostConstruct
+ public void setup() {
+ this.listener = new VisaApplicationPrometheusProcessEventListener("acme-travels");
+ register(this.listener);
+ }
+
+ @PreDestroy
+ public void close() {
+
+ this.listener.cleanup();
+ }
+}
diff --git a/03-kogito-visas/src/main/java/org/kie/kogito/app/RuleEventListenerConfig.java b/03-kogito-visas/src/main/java/org/kie/kogito/app/RuleEventListenerConfig.java
new file mode 100644
index 00000000000..8ddf512fb61
--- /dev/null
+++ b/03-kogito-visas/src/main/java/org/kie/kogito/app/RuleEventListenerConfig.java
@@ -0,0 +1,15 @@
+package org.kie.kogito.app;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import org.drools.core.config.DefaultRuleEventListenerConfig;
+import org.kie.addons.monitoring.rule.PrometheusMetricsDroolsListener;
+
+@ApplicationScoped
+public class RuleEventListenerConfig extends DefaultRuleEventListenerConfig {
+
+
+ public RuleEventListenerConfig() {
+ super(new PrometheusMetricsDroolsListener("acme-travels"));
+ }
+}
diff --git a/03-kogito-visas/src/main/java/org/kie/kogito/app/VisaApplicationPrometheusProcessEventListener.java b/03-kogito-visas/src/main/java/org/kie/kogito/app/VisaApplicationPrometheusProcessEventListener.java
new file mode 100644
index 00000000000..f4e2f05d731
--- /dev/null
+++ b/03-kogito-visas/src/main/java/org/kie/kogito/app/VisaApplicationPrometheusProcessEventListener.java
@@ -0,0 +1,61 @@
+package org.kie.kogito.app;
+
+import org.acme.travels.VisaApplication;
+import org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl;
+import org.kie.addons.monitoring.process.PrometheusProcessEventListener;
+import org.kie.api.event.process.ProcessCompletedEvent;
+
+import io.prometheus.client.CollectorRegistry;
+import io.prometheus.client.Counter;
+
+public class VisaApplicationPrometheusProcessEventListener extends PrometheusProcessEventListener {
+
+ protected final Counter numberOfVisaApplicationsApproved = Counter.build()
+ .name("acme_travels_visas_approved_total")
+ .help("Approved visa applications")
+ .labelNames("app_id", "country", "duration", "nationality")
+ .register();
+
+ protected final Counter numberOfVisaApplicationsRejected = Counter.build()
+ .name("acme_travels_visas_rejected_total")
+ .help("Rejected visa applications")
+ .labelNames("app_id", "country", "duration", "nationality")
+ .register();
+
+ private String identifier;
+
+ public VisaApplicationPrometheusProcessEventListener(String identifier) {
+ super(identifier);
+ this.identifier = identifier;
+ }
+
+ public void cleanup() {
+ CollectorRegistry.defaultRegistry.unregister(numberOfVisaApplicationsApproved);
+ CollectorRegistry.defaultRegistry.unregister(numberOfVisaApplicationsRejected);
+ }
+
+ @Override
+ public void afterProcessCompleted(ProcessCompletedEvent event) {
+ super.afterProcessCompleted(event);
+ final WorkflowProcessInstanceImpl processInstance = (WorkflowProcessInstanceImpl) event.getProcessInstance();
+
+ if (processInstance.getProcessId().equals("visaApplications")) {
+ VisaApplication application = (VisaApplication) processInstance.getVariable("visaApplication");
+
+ if (application.isApproved()) {
+ numberOfVisaApplicationsApproved.labels(identifier, safeValue(application.getCountry()), String.valueOf(application.getDuration()), safeValue(application.getNationality())).inc();
+ } else {
+ numberOfVisaApplicationsRejected.labels(identifier, safeValue(application.getCountry()), String.valueOf(application.getDuration()), safeValue(application.getNationality())).inc();
+ }
+
+ }
+ }
+
+ protected String safeValue(String value) {
+ if (value == null) {
+ return "unknown";
+ }
+
+ return value;
+ }
+}
diff --git a/03-kogito-visas/src/main/resources/META-INF/resources/index.html b/03-kogito-visas/src/main/resources/META-INF/resources/index.html
new file mode 100644
index 00000000000..817c1dd0a6c
--- /dev/null
+++ b/03-kogito-visas/src/main/resources/META-INF/resources/index.html
@@ -0,0 +1,214 @@
+
+
+
+
+ Kogito Visas
+
+
+
+
+
+
+
+
+