In this approach it requires coding, to provide an implementation in the application responsible to execute the task, in this case, a REST/HTTP call. The implementation is up to the user, but here it's been used what the platform provides, like the RestTemplate. Details can be seen in the classes LicenseValidationRestService and TrafficViolationRestService.
The BPMN file where this process is declared is traffic-rules-dmn-service-task.bpmn
This is a declarative approach, it does not require to have any extra implementation, the REST/HTTP call is executed out-of-the-box by the engine. The information needed to execute the REST call, like the URL and HTTP method should be set in the Data Assignments in the REST Work Item.
The BPMN file where this process is declared is traffic-rules-dmn-wih.bpmn
These are the properties defined for the process, the most important one in this section to pay attention is the ID because it is used in the REST endpoint generation referring to the path to interact with this process.
The variables used in the process itself, but the focus in this example are the classes that are used to define the POJOs to interact the process with decisions, that are the Violation, Driver, Fine and TrafficViolationResponse.
Mapping data from Process to/from DMN
It is important to mention DMN for instance can define the Data Type in its structure, but we can align all attributes names in a Java class that is used as process variables, in case the attribute names contain spaces or are not following java conventions we can use Jackson annotations to make the process variable POJOs aligned with DMN data types, for instance in the Violation class, where it is mapped the speedLimit
attribute as Speed Limit
using @JsonProperty
annotation, in this case, this attribute from the process variable with Violation can be seamlessly integrated Violation Data Type defined in DMN.
Violation Data Type in DMN
Fetch for driver information, in this implementation it is just mocking a result, that simply fill with an expired license date in case the driverId
is an odd number and with a valid date in case of an even number. In a real use case, it could be performing an external call to a service or a database to get this information.
The service task implementation is done in the DriverService class.
In the data assignment the input is the driverId
and output is the driver
variable, filled with all driver information.
Represents the task to do the call to the DRL service.
Service Task
The implementation properties where it is necessary to set the Java class implementing the task that executes the call should be set alongside the method. The URL configuration is done in the application.properties.
The input and output mapping for this task is just the driver variable that is filled with license validation information.
REST Work Item
The input and output mapping for this task is just the driver variable that is filled with license validation information. For REST Work Item the URL and HTTP Method are set as input parameters in the process itselt, that is differnt from the Service Task approach.
Similar to the License Validation Task, but it represents the task to do the call to the DMN service.
Service Task
The implementation properties where it is necessary to set the Java class implementing the task that executes the call should be set alongside the method.
The input for this task is the Driver
and Violation
variables, and the output is the Suspended
and Fine
that are wrapped into the TrafficViolationResponse.
REST Work Item
The input for this task is the Driver
and Violation
variables, and the output is the Suspended
and Fine
that are wrapped into the TrafficViolationResponse. For REST Work Item the URL and HTTP Method are set as input parameters in the process itselt, that is different from the Service Task approaach.
Just an example task where it could be performed any action based on the condition in which the driver is suspended. In the current implementation, it is just logging the information in the console.
Just an example task where it could be performed any action based on the condition in which the driver is not suspended. In the current implementation, it is just logging the information in the console.
This decision consistis in rules which are evaluated to check if a driver's license is expired or not according to the expiration date and thus populating the result in the information in the driver variable.
The DRL file where this Rule Unit is declared is LicenseValidationService.drl and the the Java class that contains the Rule Unit Data is LicenseValidationService.
This decision consists in a DMN that basically checks if a driver is suspended or not according to the violation and current driver points in its license.
The DMN file where this decision is declared is TrafficViolation.dmn
You will need:
mvn clean spring-boot:run
mvn clean package java -jar target/process-decisions-rest-springboot.jar
or on windows
mvn clean package java -jar target\process-decisions-rest-springboot.jar
You can take a look at the OpenAPI definition - automatically generated and included in this service - to determine all available operations exposed by this service. For easy readability you can visualize the OpenAPI definition file using a UI tool like for example available Swagger UI.
In addition, various clients to interact with this service can be easily generated using this OpenAPI definition.
Once the service is up and running we can invoke the REST endpoints and examine the logic. There should be two process running under the following URLs:
http://localhost:8080/traffic_service
http://localhost:8080/traffic_wih
To make use of this application it is as simple as putting a sending request to http://localhost:8080/traffic_service
or http://localhost:8080/traffic_wih
with appropriate contents. See the following cases:
Given data:
{ "driverId": "12345", "violation":{ "Type":"speed", "Speed Limit": 100, "Actual Speed":140 } }
Submit the JSON object from above:
curl -X POST -H 'Content-Type:application/json' -H 'Accept:application/json' -d '{"driverId": "12345","violation":{"Type":"speed","Speed Limit": 100,"Actual Speed":140}}' http://localhost:8080/traffic_service
or
curl -X POST -H 'Content-Type:application/json' -H 'Accept:application/json' -d '{"driverId": "12345","violation":{"Type":"speed","Speed Limit": 100,"Actual Speed":140}}' http://localhost:8080/traffic_wih
After the Curl command you should see a similar console log
{ "id": "e499326d-3bd2-4ddb-93b7-0f68f74a9673", "driverId": "12345", "driver": { "licenseExpiration": "2021-08-12T19:35:48.971+00:00", "validLicense": true, "Name": "Arthur", "State": "SP", "City": "Campinas", "Points": 13, "Age": 30 }, "trafficViolationResponse": { "Fine": { "Amount": 1000.0, "Points": 7 }, "Suspended": "Yes" }, "violation": { "Code": null, "Date": null, "Type": "speed", "Speed Limit": 100, "Actual Speed": 140 } }
You can play with different attributes, if the driverId
is an odd number in this case 12345
the license will be evaluated as valid because the DriverService generates a valid expiration date and DMN is evaluated, you can change the actual speed to 140 or 100 to simulate the driver suspension on the DMN evaluation.
If the driverId
is an even number like 1234
the license will be evaluated as expired and the DMN will not be evaluated, so Suspended response attribute should be null
.
Given data:
{ "driverId": "1234", "violation":{ "Type":"speed", "Speed Limit": 100, "Actual Speed":110 } }
Submit the JSON object from above:
curl -X POST -H 'Content-Type:application/json' -H 'Accept:application/json' -d '{"driverId": "1234","violation":{"Type":"speed","Speed Limit": 100,"Actual Speed":110}}' http://localhost:8080/traffic_service
or
curl -X POST -H 'Content-Type:application/json' -H 'Accept:application/json' -d '{"driverId": "1234","violation":{"Type":"speed","Speed Limit": 100,"Actual Speed":110}}' http://localhost:8080/traffic_wih
After the Curl command, you should see a similar console log
{ "id": "fffd3f08-045b-4935-a312-0901c4120f19", "driverId": "1234", "driver": { "licenseExpiration": "2021-08-11T19:43:44.130+00:00", "validLicense": false, "Name": "Arthur", "State": "SP", "City": "Campinas", "Points": 13, "Age": 30 }, "trafficViolationResponse": null, "violation": { "Code": null, "Date": null, "Type": "speed", "Speed Limit": 100, "Actual Speed": 110 } }
In this case the driver license is expired when the DRL is evaluated because the DriverService generated an expired date for the driver's license thus DMN is not evaluated, so the validLicense
is false
and trafficViolationResponse
is null
.