- 1) Pre requisites
- 2) Generate the project skeleton
- 3) Verify if everything is fine
- 4) Install the Kogito Extension in VSCode
- 5) Import the generated project into VSCode
- 6) Import the required resources to the project
- 7) Run the test rules
- 8) Create service classes
- 9) Create the business logic for the Hotel Booking
- 10) Create the business logic for the Flight Booking
- 11) Create the business logic for the Travel Request
- 12) Verify the REST Endpoints
- 13) Verify the User Interface
- Solution
- Resources
Created by gh-md-toc
Make sure that you have everything set and installed before continue:
- OpenJDK 8+
- VSCode 1.41.1
- Kogito VSCode extension (latest)
- Red Hat Java VSCode extension (latest)
- Maven 3.6.0+
- Git
mvn io.quarkus:quarkus-maven-plugin:1.1.1.Final:create \
-DprojectGroupId=org.acme.travel \
-DprojectArtifactId=kogito-travel-agency \
-Dextensions="kogito,openapi"
This command will generate the following project structure:
ll kogito-travel-agency/
total 28
-rwxrwxr-x. 1 ricferna ricferna 10078 Jan 24 10:47 mvnw
-rw-rw-r--. 1 ricferna ricferna 6609 Jan 24 10:47 mvnw.cmd
-rw-rw-r--. 1 ricferna ricferna 3967 Jan 24 10:47 pom.xml
-rw-rw-r--. 1 ricferna ricferna 1188 Jan 24 10:47 README.md
drwxrwxr-x. 4 ricferna ricferna 80 Jan 24 10:47 src
Run the following commands and wait a little bit to verify if the project was generated correctly:
cd kogito-travel-agency
mvn compile quarkus:dev
Open your favorite web browser and go to http://localhost:8080. A default welcome Quarkus page should open.
- Download the latest Visual Studio plugin from the project page: https://github.com/kiegroup/kogito-tooling/releases
- Select the latest version
- From asset section download the file
vscode_extension_kogito_kie_editors_0.2.7.vsix
(the version might change) - Open Visual Studio Code
- Select the Extensions pane on the left
- Click the
...
icon on the top right - Select Install from VSIX...
- Open Visual Studio Code
- Go to "File", "Add Folder to Workspace"
- Select the Folder
kogito-travel-agency
in your file system - Click "Add"
Alternatively, you could run the following command on your terminal:
code kogito-travel-agency
kogito-travel-agency
is the project folder.
In this step you will import the required data objects (Address.java
, Flight.java
, Hotel.java
, Traveller.java
, Trip.java
) . A decision table will also be added to your project under resources/org/acme/travel/visa-rules.xls
. Finally, two tests are going to be imported TravelTest.java
and VisaRulesTest.java
.
- Clone the DevConf 2020 Workshop:
# make sure to exit from the kogito-travel-agency directory
cd …
git clone https://github.com/cristianonicolai/devconfcz-2020
- Move the domain data and test files to your project:
cp -r devconfcz-2020/src/* kogito-travel-agency/src/
- Make sure that everything is compiling:
cd kogito-travel-agency
mvn clean compile
- Add the following dependency in the
pom.xml
file in the project root just after the tag<dependencies>
<dependency>
<groupId>org.kie.kogito</groupId>
<artifactId>drools-decisiontables</artifactId>
</dependency>
- Run the tests
mvn clean verify
All tests should pass.
Add the following two clases which will be a flight and hotel services, inside the src/main/java/org/acme/travel/service
folder:
-
Create
FlightBookingService
, a CDI bean with anApplicationScoped
annotation, that contains one method, receiving aTrip
object and returning aFlight
one. -
Create
HotelBookingService
, a CDI bean with anApplicationScoped
annotation, that contains one method, receiving aTrip
object and returning aHotel
one. -
Verify your work
mvn clean verify
- On
src/main/resources/org/acme/travel
, create new BPMN file namedhotelBooking.bpmn2
for the Hotel booking sub-process. Since you have installed an extension, VSCode will automatically open a BPMN editor for you. Using the BPMN editor, set the following process attributes (properties panel on right side):
- Process Name: Hotel Booking
- Id: hotelBooking
- Package:
org.acme.travel
- Process data:
Add two process variables:
- Name: hotel Data type (custom):
org.acme.travel.Hotel
- Name: trip Data type (custom):
org.acme.travel.Trip
- Name: hotel Data type (custom):
Important! Save your work: ctrl+s (Or cmd+s if you are using mac)
- Model Hotel Booking process
- Add a start node, a service task for executing the
HotelBookingService
bean and an end node. - Select the new service task node:
- Configure it's name, you can set it with the name
Book Hotel
; - Modify the following properties (Implementation/Execution):
- Select Implementation Java
- Interface, the complete name (FQDN) of the
HotelBookingService
class:org.acme.travel.service.HotelBookingService
- Operation, the name of the method that you created in the
HotelBookingService
class service. - Assignments:
- Input: Add an input named Parameter of type (custom)
org.acme.travel.Trip
and source trip. - Output: Add an output named Result of type (custom)
org.acme.travel.Hotel
and source hotel.
- Input: Add an input named Parameter of type (custom)
- Configure it's name, you can set it with the name
Important! Save your work: ctrl+S (or cmd+s)
- On
src/main/resources/org/acme/travel
, create new BPMN file namedflightBooking.bpmn2
for the Flight booking sub-process. Using the BPMN editor, set the following process attributes (properties panel on right side):
- Process Name: Flight Booking
- Id: flightBooking
- Package:
org.acme.travel
- Process data:
Add two process variables:
- Name: flight Data type (custom):
org.acme.travel.Flight
- Name: trip Data type (custom):
org.acme.travel.Trip
- Name: flight Data type (custom):
Important! Save your work: ctrl+S
- Model Flight Booking process
- Add a start node, a service task for executing the
FlightBookingService
bean and an end node. - Select the new service task node and:
- Name it as Book flight
- Modify the following properties (Implementation/Execution):
- Select Implementation Java
- Interface, the fully complete name of the
FlightBookingService
class:org.acme.travel.service.FlightBookingService
- Operation, the name of the method that you created in the
FlightBookingService
class service. - Assignments:
- Input: Add an input named Parameter of type
org.acme.travel.Trip
and source trip. - Output: Add an output named Result of type
org.acme.travel.Flight
and source flight.
- Input: Add an input named Parameter of type
Important! Save your work: ctrl+S (or cmd+s)
- On
src/main/resources/org/acme/travel
, create new BPMN file for the Travels process. Using the BPMN editor, set the following process attributes (properties panel on right side):
- Process Name: Travels
- Id: travels
- Package:
org.acme.travel
- Process data (add the following process variables):
- Name: flight Data type (custom):
org.acme.travel.Flight
- Name: trip Data type (custom):
org.acme.travel.Trip
- Name: hotel Data type (custom):
org.acme.travel.Hotel
- Name: traveller Data type (custom):
org.acme.travel.Traveller
- Name: flight Data type (custom):
Important! Save your work: ctrl+S
- Model Travel process
- Add start node
- From start node, add Visa Check rule node with the following attributes:
- Name: Visa Check
- Implementation/Execution
- Rule Language: DRL
- Rule Flow Group (new): visas
- Data Assignments
- Input:
- Add an input named trip of type (custom)
org.acme.travel.Trip
and source trip. - Add an input named traveller of type (custom)
org.acme.travel.Traveller
and source traveller.
- Add an input named trip of type (custom)
- Output:
- Add an output named trip of type
org.acme.travel.Trip
and target trip.
- Add an output named trip of type
- Input:
Important! Save your work: ctrl+S
- From Visa Check, add an exclusive gateway
- From the exclusive gateway, add a user task named Visa Application with the following attributes
- Implementation/Execution, Task Name: VisaApplication
- Select the connecting arrow between the exclusive gateway and the Visa Application task and set the following attribute:
- Implementation/Execution, Expression radio button:
return trip.isVisaRequired();
- Add new exclusive gateway and connect both nodes Visa Application and previous exclusive gateway, creating a fork in the process model.
- Select the connecting arrow between both exclusive gateways and set the following attribute:
- Implementation/Execution, Expression radio button:
return !trip.isVisaRequired();
- From the newly created exclusive gateway, add new parallel gateway.
- From the parallel gateway, add new reusable sub-process for Book Hotel process with the following attributes:
- Implementation/Execution, Called Element (new): hotelBooking
- Data Assignments
- Input: Add an input named trip of type (custom)
org.acme.travel.Trip
and source trip. - Output: Add an output named hotel of type
org.acme.travel.Hotel
and source hotel.
- Input: Add an input named trip of type (custom)
Important! Save your work: ctrl+S
- From the parallel gateway add new reusable sub-process for Book Flight process with the following attributes:
- Implementation/Execution, Called Element (new): flightBooking
- Data Assignments
- Input: Add an input named trip of type (custom)
org.acme.travel.Trip
and source trip. - Output: Add an output named flight of type (custom)
org.acme.travel.Flight
and source flight. - Click Save
- Input: Add an input named trip of type (custom)
Important! Save your work: ctrl+S
- Add new parallel gateway and connect both reusable sub-process nodes into it.
- From the parallel gateway, add new user task named Confirm Travel with the following attributes:
- Task Name: ConfirmTravel
- From the Confirm Travel, add an end node.
Important! Save your work: ctrl+S
To test your process, uncomment the tests (CTRL+K, CTRL+U or CMD+K,CMD+U when using a mac) on src/test/java/org/acme/travel/TravelTest.java
and execute:
mvn clean verify
Your test will fail because the assertions are expecting fixed values that are being returned from your services. Make sure to fix your services and try again.
- Run the following command to execute your Kogito application:
mvn clean quarkus:dev
- Verify travels endpoint:
curl -X GET http://localhost:8080/travels
Should return an empty array since you don’t have any travels yet.
- Post new Travel that does not require visa
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
Make note of the returned id
field, since your will need it from now on.
- Get open tasks for current process, should return
ConfirmTravel
(replace{uuid}
with theid
field returned in the previous step):
curl -X GET http://localhost:8080/travels/{uuid}/tasks
Make note of the returned id
field, since your will need it from now on in the task-uuid
placeholders.
- Completes confirms travel task - meaning confirms (and completes) the travel request:
Replace {uuid}
with the id
returned from the step #3 and {task-uuid}
with the id from the previous step (#4):
curl -H "Content-Type: application/json" -H "Accept: application/json" -X POST http://localhost:8080/travels/{uuid}/ConfirmTravel/{task-uuid} -d '{}'
You should receive a reply similar to this one:
{"id":"966aa8a3-0e3f-4263-8e0e-780170e846e5","flight":{"flightNumber":"MX555","seat":"34B","gate":"C4","departure":1575928800000,"arrival":1575928800000},"trip":{"city":"New York","country":"US","begin":1575928800000,"end":1576360800000,"visaRequired":false},"hotel":{"name":"Perfect hotel","address":{"street":"34 Great Streat","city":"New York","zipCode":"05644","country":"US"},"phone":"09876543","bookingNumber":"XX-012345","room":"69"},"traveller":{"firstName":"John","lastName":"Doe","email":"john.doe@example.com","nationality":"American","address":{"street":"main street","city":"Boston","zipCode":"10005","country":"US"}}}
- Verify process has finished (replace
{uuid}
with the sameid
from the travels endpoint)
curl -X GET http://localhost:8080/travels/{uuid}
You’ll receive an empty response, the process has finished and there’s no reason to keep the travel anymore.
- Post new Travel that does require visa
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
Make note of the returned id
field, since your will need it from now on.
- Get open tasks for current process, should return
VisaApplication
(replace{uuid}
with theid
field returned in the previous step):
curl -X GET http://localhost:8080/travels/{uuid}/tasks
Make note of the returned id
field, since your will need it from now on in the task-uuid
placeholders.
- Completes Visa Application request. Replace
{uuid}
with theid
returned from the step #7 and{task-uuid}
with the id from the previous step (#8):
curl -H "Content-Type: application/json" -H "Accept: application/json" -X POST http://localhost:8080/travels/{uuid}/VisaApplication/{task-uuid} -d '{}'
- Get open tasks for current process, should return
ConfirmTravel
. Replace{uuid}
with the travelid
:
curl -X GET http://localhost:8080/travels/{uuid}/tasks
- Completes confirms travel task - meaning confirms (and completes) the travel request. Replace the ids placeholders accordingly:
curl -H "Content-Type: application/json" -H "Accept: application/json" -X POST http://localhost:8080/travels/{uuid}/ConfirmTravel/{task-uuid} -d '{}'
- Verify process has finished:
curl -X GET http://localhost:8080/travels/{uuid}
You’ll receive an empty response, the process has finished and there’s no reason to keep the travel anymore.
Explore Swagger UI on http://localhost:8080/swagger-ui/
Plan new travel requests using the Travel Agency UI available on http://localhost:8080/
Just clone the branch solved
:
git clone -b solved --single-branch git@github.com:cristianonicolai/devconfcz-2020.git devconfcz-2020-solved
Run the application:
cd devconfcz-2020-solved
mvn clean verify quarkus:dev