In our first tutorial about DMN – Getting 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: https://sandbox.kie.org/#
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:
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”:
Within the Decision Table, add the following logic:
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:
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:
<dependency> <groupId>org.kie.kogito</groupId> <artifactId>kogito-quarkus-decisions</artifactId> </dependency>
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:
src ├── main │ ├── docker │ │ ├── Dockerfile.jvm │ │ ├── Dockerfile.legacy-jar │ │ ├── Dockerfile.native │ │ └── Dockerfile.native-distroless │ └── resources │ ├── application.properties │ └── discount.dmn └── test ├── java │ ├── org │ │ └── acme │ │ ├── NativePricingIT.java │ │ └── PricingTest.java │ └── testscenario └── resources
Great. Now we will edit the PricingTest.java 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 org.hamcrest.CoreMatchers.is; @QuarkusTest public class PricingTest { @Test public void testBasePrice() { given() .body("{ \"Purchase\": 50, \"PrimeCustomer\": true }") .contentType(ContentType.JSON) .when() .post("/discount") .then() .statusCode(200) .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] [INFO] Results: [INFO] [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:
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-smallrye-openapi</artifactId> </dependency>
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:
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: https://github.com/fmarchioni/mastertheboss/tree/master/quarkus/kogito-dmn