DMN example application with Quarkus

In our first tutorial about DMNGetting started with Decision Models (DMN) – we have covered the foundation of Decision Models and the key components in it. In this follow up article we will design and create an example application which exposes a simple Decision Model through Quarkus REST Services.

Designing the Decision Model

To design the example Decision Model we recommend the Kie SandBox which is ideal if you want to experiment with KIE applications like jBPM or Kogito.

Move to:

To test your Model, you need to install the DMN Runner. That is a Quarkus native applications that enables running your models and see live forms and results as you edit. Just click on the Run button from the Kie SandBox and follow the installing instructions.

To start the DMN runner, simply execute the Quarkus DMN Runner for your platform:

$ kie_tooling_extended_services

Now let’s design a simple Model named “discount”:

Here is the Diagram of our Model:

Decision Model example

As you can see from the above picture, our DMN includes:

  • An input parameter of type number named Purchase
  • An input parameter of type boolean named PrimeCustomer
  • A Decision Node named Discount

Next, click on “Edit” in your Decision Node and choose as expression “Decision Table”:

dmn tutorial java

Within the Decision Table, add the following logic:

Decision Model example

So, as you can see, a PrimeCustomer is granted a 20% discount off the price for orders greater/equal to 50. A regular Customer is granted a 10% discount as well for orders >= 50.

Since we have enabled the DMN runner we can see live results of our Model’s Output:

dmn example

Running the Model with Quarkus

Quarkus application can leverage Kogito to add business automation and add DMN decision support. The required extension to include in your project is:


Next, we will include the DMN file. To do that, from the Kie Sandbox choose Share | Download to download locally the DMN file of our Model and copy it under src/main/resources of your Quarkus project:

├── main
│   ├── docker
│   │   ├── Dockerfile.jvm
│   │   ├── Dockerfile.legacy-jar
│   │   ├── Dockerfile.native
│   │   └── Dockerfile.native-distroless
│   └── resources
│       ├──
│       └── discount.dmn
└── test
    ├── java
    │   ├── org
    │   │   └── acme
    │   │       ├──
    │   │       └──
    │   └── testscenario
    └── resources

Great. Now we will edit the Test class to include the Input fields and the expected Output:

package org.acme;

import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType;

import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static;

public class PricingTest {

    public void testBasePrice() {
          .body("{ \"Purchase\": 50, \"PrimeCustomer\": true }")
            .body("'Discount'", is(10));

Therefore, according to our Test, with a Purchase of 50 a PrimeCustomer should receive a discount of 10.

Please notice that Kogito automatically creates the default endpoint “/discount” for the DMN with that name.

Run the test:

$ mvn test

. . . .
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 12.979 s - in org.acme.PricingTest
2021-12-09 17:19:34,724 INFO  [io.quarkus] (main) Quarkus stopped in 0.032s
[INFO] Results:
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

Accessing the DMN Endpoint from Swagger

You can also test your Model using Swagger UI. That requires to include the OpenAPI dependency in your project:


Next, restart your Quarkus application in dev mode:

$ mvn quarkus:dev

Finally, access Swagger UI from: http://localhost:8080/q/swagger-ui/

You will see that the following endpoints are available:

Decision Model example

Create a POST request with some input parameters:

curl -X 'POST' \
  'http://localhost:8080/discount' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "Purchase": 100,
  "PrimeCustomer": true

That will return the following response:

  "Purchase": 100,
  "Discount": 20,
  "PrimeCustomer": true

Source code available here: