This example showcases a basic implementation of the Hiring process that drives a Candidate through different interviews until he gets hired.
This quickstart project shows a simple example user task orchestration including the use of DMN decisions to generate the candidate offer and tÂşimers to skip User Tasks.
This example also demonstrates how to configure the whole Kogito environment using the new Compact Architecture that enable simplifying the communication among Kogito services removing the need of events (Kafka/HTTP) between them. This can be achieved using the following Quarkus addons:
kogito-addons-quarkus-data-index-persistence-postgresql
: enables the Kogito Runtime persisting directly into the Data-Index database.kogito-addons-quarkus-jobs
: enables collocating the Jobs Service inside the Kogito Runtime.
The Hiring process uses two POJOs to handle the process data, both of them can be found in the org.kie.kogito.hr package.
The CandidateData
POJO is the input of the process. It represents the person that wants to get the job.
public class CandidateData {
private String name; // Name of the candidate
private String lastName; // Last name of the candidate
private String email; // Email of the candidate
private Integer experience; // Years of experience
private List<String> skills; // List of technical skills
// Constructors, setters, getters...
}
The Offer
POJO is the output of the process and represents the job offer that will be sent to the candidate.
It will be automatically calculated during the process execution depending on the candidate years of experience & skills.
public class Offer {
private String category; // Job category based on the candidate experience
private Integer salary; // Salary based on the candidate experience and skills
// Constructors, setters, getters...
}
This example makes use of the New Hiring Offer DMN to generate a base offer for the Candidate
. The DMN looks like this:
In this simple DMN we have an Offer
Decision, that will generate the candidate offer, which
has a requirement of a CandidateData
Input Data.
The DMN defines the following data types (tCandidateData
& tOffer
) matching the POJOs defined in the project
(CandidateData.java
& Offer.java
):
As expected, CandidateData
Input Data & Offer
Decision have a tCandidateData
data
The Offer
decision uses the following Boxed Expression to generate the tOffer
:
The process handles the following Variables:
Variable | Type | Tags | Description |
---|---|---|---|
candidateData | org.kie.kogito.hr.CandidateData |
input | The candidate data |
offer | org.kie.kogito.hr.Offer |
output | The generated candidate offer |
hr_approval | Boolean |
internal | Determines that HR department approves the hiring |
it_approval | Boolean |
internal | Determines that IT department approves the hiring |
The process starts receiving the CandidateData
as an input and storing it into the candidateData
variable, and if the
candidate meets two minimal requirements, the process will continue and reach the Generate base offer, otherwise the
candidate application will be denied and the process will complete without sending the offer
to the candidate.
The Generate base offer is a Business Rule Task that will use the New Hiring Offer decision defined in the
NewHiringOffer.dmn
to generate the an Offer
based on the candidate experience and skills. The task takes the candidateData
as an input and will produce an instance of org.kie.kogito.hr.Offer
that will be stored in the offer
variable.
After the offer
has been generated, the process will jump into the HR Interview User Task, where the candidate we'll
be interviewed by the HR department. The task takes the candidateData
and offer
as inputs and as an output will produce
the hr_approve
boolean and an updated offer
.
The HR Interview User Task also has a Boundary Timer Event that will prevent the task to delay and will cancel the task after certain time (for example purpose just 3 minutes). This Boundary Timer Event will schedule a Job in the Jobs Service that when trigger will notify the Kogito Runtime to cancel the task and deny the application.
If HR Interview successfully completed, the process will jump into the IT Interview User Task. Again the candidate
we'll have a second interview with the IT department. Again, this task will take the candidateData
and offer
as inputs
but as an output will produce the it_approve
boolean.
Once both tasks are completed, if the candidate got the approvals from HR & IT (both hr_interview
& hr_interview
being true)
the process will jump into the Send Offer to Candidate Script Task that will notify the candidate about the offer
and the process will end.
NOTE: for simplicity, all the User Tasks in this example are assigned to the jdoe user present in the keycloak configuration
- Java 17+ installed
- Environment variable JAVA_HOME set accordingly
- Maven 3.9.3+ installed
- Docker and Docker Compose to run the required example infrastructure.
And when using native image compilation, you will also need:
- GraalVM 20.3+ installed
- Environment variable GRAALVM_HOME set accordingly
- GraalVM native image needs as well native-image extension: https://www.graalvm.org/reference-manual/native-image/
- 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.
This quickstart provides a docker compose template that starts all the required services. This setup ensures that all services are connected with a default configuration.
- PostgreSQL: 5432
- Management Console: 8280
- Task Console: 8380
- Keycloak: 8480
- PgAdmin: 8055
- Kogito Example Service: 8080
To help bootstraping the Infrastructure Services, the example provides the startServices.sh
script inside the docker-compose
folder.
NOTE: the docker compose template requires using extra_hosts to allow the services use the host network, this may carry some issues if you are using a podman version older than 4.7.
To build the example, on a Terminal, run the following command:
mvn clean package -Pcontainer
This will build the example quarkus application and create a Docker image that will be started in the docker-compose
template.
To execute the full example (including consoles), open a Terminal and run the following command inside the docker-compose
folder:
sh startServices.sh
IMPORTANT: if you are running this example on MacOs and you are not using Docker Desktop, please append the following entry in your
/etc/hosts
file to enable a good communication between al components.127.0.0.1 kubernetes.docker.internal
Additionally, if you want to start only the example and the minimal Infrastructure Services (PostgreSQL, Data-Index and Jobs Service),
you can run the same startServices.sh
script but passing the example
argument
sh startServices.sh example
NOTE: starting the Infrastructure Services, please consider running a
mvn clean package -Pcontainer
command on the project root before running thestartServices.sh
script for the first time or any time you modify the project.
To run the example in Development mode, just run the following command in a Terminal:
mvn clean package quarkus:dev -Pdevelopment
The Development Mode will embed all the needed Infrastructure Services (PostgreSQL, Data-Index & Jobs Service) and won't require any extra step.
The development
profile includes the Runtime Tools Quarkus Extension that exposes a new section in the Quarkus Dev-UI
unifying the Management Console & Task Console functionalities. Quarkus Dev-UI is available at http://localhost:8080/q/dev
NOTE: For more information about how to work with Kogito Runtime Tools Quarkus Extension, please refer to the Kogito Documentation page.
Once the service is up and running you can make use of the Hiring application by a sending request to http://localhost:8080/hiring
.
Sending the following valid CandidateData
will start a process instance that will land into the HR Interview task:
{
"candidateData": {
"name": "Jon",
"lastName": "Snow",
"email": "[email protected]",
"experience": 5,
"skills": ["Java", "Kogito", "Fencing"]
}
}
In a Terminal you can execute this curl command to start a Hiring process:
curl -H "Content-Type: application/json" -H "Accept: application/json" -X POST http://localhost:8080/hiring -d '{"candidateData": { "name": "Jon", "lastName": "Snow", "email": "[email protected]", "experience": 5, "skills": ["Java", "Kogito", "Fencing"]}}'
If everything went well you may get a response like:
{
"id": "628e679f-4deb-4abc-9f28-668914c64ef9",
"offer": {
"category": "Senior Software Engineer",
"salary": 40450
}
}
In the server log You may find a trace like:
New Hiring has been created for candidate: Jon Snow
###################################
Generated offer for candidate: Jon Snow
Job Category: Senior Software Engineer
Base salary: 40450
###################################
Use the following CandidateData
that don't match the minimal candidate requirements, to start a process that will automatically end:
{
"candidateData": {
"name": "Jon",
"lastName": "Snow",
"email": "[email protected]",
"experience": 0,
"skills": []
}
}
In a Terminal you can execute this curl command to start a Hiring process:
curl -H "Content-Type: application/json" -H "Accept: application/json" -X POST http://localhost:8080/hiring -d '{"candidateData": { "name": "Jon", "lastName": "Snow", "email": "[email protected]", "experience": 0, "skills": []}}'
If everything went well you may get a response like:
{
"id": "3659601a-bb59-458d-859e-7892621ad5b7",
"offer": null
}
In the server log You may find a trace like:
New Hiring has been created for candidate: Jon Snow
###################################
Candidate Jon Snow don't meet the requirements for the position but we'll keep it on records for the future!
###################################
In this Quickstart we'll be using Keycloak as Authentication Server. It will be started as a part of the project Infrastructure Services, you can check the configuration on the project docker-compose.yml in docker-compose folder.
It will install the Kogito Realm that comes with a predefined set of users:
Login | Password | Roles |
---|---|---|
admin | admin | admin, managers |
alice | alice | user |
jdoe | jdoe | managers |
Once Keycloak is started, you should be able to access your Keycloak Server at localhost:8480/auth with admin user.
NOTE: This example uses keycloak authentication to enable security only in the consoles not in runtime.
The following step-by-step guides will show how to take advantage of both Kogito Management Console and Kogito Task Console to operate with the instances of Hiring process.
To be able to follow the guides, please make sure that the example has been built using the container
and all the Infractructure Services
are started as explained in the Building & Running the example section.
NOTE: For more information about how to operate with the Kogito Runtime Consoles, please refer to the Management Console & Task Console documentation.
Kogito Management Console is the tool that enables the user to view and administrate process instances in our Kogito application.
In this guide we'll see how to use the Kogito Management Console to view the state of the Hiring process instances.
-
With the example built and all the Infrastructure Services running, let's start an instance of the Hiring process. To do so, in a Terminal just run:
curl -H "Content-Type: application/json" -H "Accept: application/json" -X POST http://localhost:8080/hiring -d '{"candidateData": { "name": "Jon", "lastName": "Snow", "email": "[email protected]", "experience": 5, "skills": ["Java", "Kogito", "Fencing"]}}'
If everything went well, you should get a response like:
{ "id": "064a6372-b5bb-4eff-a059-d7b24d4ac64a", "offer": { "category": "Senior Software Engineer", "salary": 40450 } }
Which indicates that a new process instance with id 064a6372-b5bb-4eff-a059-d7b24d4ac64a has been started.
-
Now let's check the process instance state with the Kogito Management Console. To do so, in your browser navigate to http://localhost:8280 and log in using any of the users specified in the Using Keycloak as Authentication Server.
Once you are logged in, you should be redirected to the Process Instances page where you should be able to see the started process instance in active state.
-
Click on the instance id to navigate into the Process Details page. In there you'll be able to see different panels displaying relevant information about the instance state, such as the Diagram, Timeline, Details, Variables, Jobs...
Now check the Diagram panel, in there you'll se the instance execution path. Notice that it's stopped HR Interview User Task waiting for some input from the user. The task has Timer that will skip the task if it's not completed in a given time (3 minutes in this example). You should be able to see the associated Job in the Jobs panel. Now, let's wait 3 minutes to see the timer in action.
-
After 3 minutes, the scheduled Job should have been executed, making the process instance skip the HR Interview task. In the Process Details page, click the Refresh button to see the process instance state.
Again, check the Diagram panel to see the process instance execution path and the HR Interview task should have been skipped and the process instance continued its execution by following the Application denied path reaching the Completed state.
Notice in the Jobs panel that the associated Job has the Executed status.
When a Kogito process reaches a User Task, the process execution stops waiting for the user input that will enable the User Task to finish and allowing the process execution to continue.
Kogito Task Console is the tool that enables the user interacting with the process User Tasks and provide the necesary data for the process to continue (usually wiht forms).
In this guide, we'll see how to complete the process User Tasks using the Kogito Task Console to interact with the process User Tasks using the engine autogenerated forms.
NOTE: For simplicity, all the User Tasks are assigned to the user jdoe. Please make sure you use the jdoe/jdoe credentials when logging in the Task Console
-
With the example built and all the Infrastructure Services running, let's start an instance of the Hiring process. To do so, in a Terminal just run:
curl -H "Content-Type: application/json" -H "Accept: application/json" -X POST http://localhost:8080/hiring -d '{"candidateData": { "name": "Jon", "lastName": "Snow", "email": "[email protected]", "experience": 5, "skills": ["Java", "Kogito", "Fencing"]}}'
If everything went well, you should get a response like:
{ "id": "3cf0d58f-a824-4046-ba6c-c2e79edc1df7", "offer": { "category": "Senior Software Engineer", "salary": 40450 } }
Which indicates that a new process instance with id 3cf0d58f-a824-4046-ba6c-c2e79edc1df7 has been started.
-
Let's check the process instance state. Again browse to http://localhost:8280 to access the Kogito Management Console, and in the Process List click the Id column to open the Process Details page.
As expected, the process instance is stopped in the HR Interview task waiting for some input from the user. Let's try to complete the task.
-
Now open the Kogito Task Console by browsing to http://localhost:8380 and login using the jdoe/jdoe credentials. After logging in, you'll be redirected to the Task Inbox page, which contains the list of Active tasks assigned to the logged user. In this case you should be able to see only the new HR Interview task.
Click on the HR Interview task to open the form and complete it!
-
The Task Form is the main component to interact with User Tasks, it allows the user to provide the data required by the task and transition it to the next phase, allowing the Process to continue. The Task Form is autogenerated based on the User Task data assignments.
HR Interview Form allows you to edit the actual Offer that will be sent to the Candidate and also approve or deny the job application with the Approve checkbox.
Now, check the Approve checkbox click the Complete button in order to submit the form and complete the task. If the task could be successfully completed, a notification should appear in the screen and the form will stay in Read-Only mode.
With the HR Interview task successfully completed the process has moved forward and reached the IT Interview task.
Optionally, you can check the process instance state in the Kogito Management Console and verify the current execution path.
-
Now is time to complete the IT Interview task and complete this Hiring process instance. In Task Console, go back to Task Inbox and as expected, there you'll see that HR Interview is no longer available and a new IT Interview has appeared.
As done in Step #3, click in the IT Interview task to open the task form. IT Interview task only needs the candidate Approval to be submitted. Please, check the Approval field and click the Complete button to submit the form.
-
After the form is submitted the IT Task should be completed and the process should continue, notifying the Candidate that he has succesfully finished the Hiring process. Please go back to Task Inbox to verify there are no other active tasks waiting for you.
You can also open use Kogito Management Console to check the state of the process instance and verify that the instance has been successfully completed.