Micronaut ft. Flowable - Rule engine validation
Flowing through business rules validation. (Example made using Micronaut, Gradle and Flowable engine using H2 local database)
Brief
We need to create an application that will run an input payload by a DMN decision table and return the decision result.
The DMN standard provides the industry with a modeling notation for decisions that will support decision management and business rules. The notation is designed to be readable by business and IT users alike.
More info about DMN features can be found here: https://camunda.com/dmn/
Enter Flowable
.
Finding
Flowable DMN is an embeddable Java engine that can run input payload through decision tables and return its result.
Moreover, it has a well documented REST API that can be used to get more in-depth details, that the Java engine may not supply: https://wwv.flowable.com/open-source/docs/dmn/ch07-REST/
Flowable also has a web interface that you can use running the Docker image provided here: https://hub.docker.com/r/flowable/all-in-one. You can create and update decision tables using the Modeler service: http://localhost:8080/flowable-modeler. The created decision tables can also be exported to dmn
files.
Setup
- Bring in Flowable engine and H2 database
- Create a simple DMN table.
(This example has a single rule that includes two inputs and one output).
- Add to the
application.yml
the database connection and the rule file location so it can be easily changed when moving to a managed database or changing the decision table.
- Define a bean of
DmnDecisionService
that can be then injected in a controller or a service.
Usage
The most straightforward explanation of how it works is: we have a set of rules defined as rows in a decision table. When querying the table, if any rule matches the data supplied, Flowable will mark the rule as true
and return the rule's output.
Depending on the hitPolicy
property defined in the decision table, we can decide if we want to return only the first rule hit, or all of those marked true. More info here: https://wwv.flowable.com/open-source/docs/dmn/ch06-DMN-Introduction/
The Flowable engine requires as an input:
- decision table key (
<decision id="RULES" name="Rules">
) - variables ( map of key and value inputs )
@Singleton
@RequiredArgsConstructor
public class FlowableService {
private final DmnDecisionService dmnDecisionService; //inject defined bean
public List<Map<String, Object>> queryFlowable(Map<String, Object> flowableQuery, String decisionKey) {
return dmnDecisionService
.createExecuteDecisionBuilder()
.decisionKey(decisionKey) // decision table key
.variables(flowableQuery) // map of column name and value
.executeDecision();
}
}
The result of the decision will be returned in the form of a list of maps of key and value outputs.
In our case:
- decisionKey:
'RULES'
- input variables:
<<input1, INPUT1>, <input2, INPUT2>>
- output:
[<output1, OUTPUT1>]
Stay tuned! 🚀