In the previous post we learned to write rules and setup KIE server. Now it’s time to integrate with it and insert our fact data. Make sure your instances of KIE server and Drools Workbench are up and running.
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aa3b6f28e060 my-kie:latest "./start_kie-server.…" 3 days ago Up About a minute 0.0.0.0:8180->8080/tcp kie-server3
5d3e05267be6 jboss/drools-workbench-showcase:latest "./start_drools-wb.sh" 4 months ago Up 48 seconds 0.0.0.0:8001->8001/tcp, 0.0.0.0:8080->8080/tcp drools-workbench
We will start with the rest api. With the following cUrl command we insert facts into the working memory. Remember that you need the credentials in order to access KIE server. By default these are kieserver/kieserver1!
Bear in mind I use a stateful session in this case which means that facts are not discarded after the requests. You will get duplicates if you will not dispose the session. This can be achieved programatically be calling dispose() method or you can restart(stop/start from workbench) the container.
Start/Stop a container
Now obviously if your application is using java you might want to go with the java client instead. In order to do that you need the kjar from the workbench repo. The idea here is that in order to insert the facts into drools engine you need to know the structure of the fact. So either you import the kjar or you mirror the structure on the application side. In this case I chose to import the kjar from the repo. This means I need to clone the workbench repo locally, build the kjar and add it as dependency.
Firstly, we need the location of the repo. That can be easily found in the workbench interface.
Project settings in drools workbench
We can clone it with the following command. Default user and pass are admin as setup in the previous post.
➜ ImportProducts git:(master) mvn clean install
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.test:ImportProducts >-----------------------
[INFO] Building ImportProducts 1.0.0-SNAPSHOT
[INFO] --------------------------------[ kjar ]--------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ ImportProducts ---
[INFO]
[INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ ImportProducts ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Using 'null' encoding to copy filtered properties files.
[INFO] Copying 7 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ ImportProducts ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /Users/sergiuoltean/fun/ImportProducts/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] Source option 6 is no longer supported. Use 7 or later.
[ERROR] Target option 6 is no longer supported. Use 7 or later.
[INFO] 2 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.840 s
[INFO] Finished at: 2021-03-05T13:06:22+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project ImportProducts: Compilation failure: Compilation failure:
[ERROR] Source option 6 is no longer supported. Use 7 or later.
[ERROR] Target option 6 is no longer supported. Use 7 or later.
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
As you see it will give you an error. This is due to the way the maven project is configured. Add the following properties to the project’s pom file(depending on your java version).
After I read the CSV and map them to facts I need to call the KIE service.
public void process(Exchange exchange) throws Exception {
List<List<String>> data = (List<List<String>>) exchange.getIn().getBody();
List<ImportProduct> products = data.stream().map(this::mapImportProducts).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(products)) {
List<? super Object> facts = new ArrayList<>(products);
final var containerId = "ImportProducts_1.0.0-SNAPSHOT";
final var mySession = "mySession";
exchange.getIn().setBody(kieService.executeCommands(containerId, facts, mySession));
} else {
log.info("Nothing to process");
}
}
The containerId is the identifier of the container deployed in the KIE server. Currently it’s the name of the maven module(by default), but you can give it an alias for easier reference. Now in the previous example with rest I chose to use a stateful session which holds the data across multiple invocations. In most of the cases you don’t need this type of behaviour. In this second example I’ve chosen a stateless session which needs a name. That’s what mySession represents. The state will not be kept across multiple invocations.
The next interesting bit it’s related on how to invoke the KIE server.
prepareCommands method prepares the facts as commands. Then we add a fire rule command and a getObjects command(which uses a filter to return only the objects we’re interested in). All these commands are bundled into a batch.
executeCommands method executes the batch against the server and uses the identifier to get the result. After this it will be written as CSV file.
Also the second rule(category price average) is triggered but since it only sys outs the result to the console we need to check the workbench logs for the results.
13:07:44,087 INFO [stdout] (default task-1) -------------------
13:26:59,175 INFO [stdout] (default task-1) Category Books
13:26:59,177 INFO [stdout] (default task-1) Price 4.5
13:26:59,179 INFO [stdout] (default task-1) -------------------
13:26:59,180 INFO [stdout] (default task-1) Category Games
13:26:59,181 INFO [stdout] (default task-1) Price 1.55
13:26:59,182 INFO [stdout] (default task-1) -------------------
I’ve mentioned that I use a stateless session. This can be setup in the workbench. A session can be created from a KIE base.
I imported your project in drools workbench and deployed it to the KIE server. I can see the container on the deploy page. I have a simple spring boot application which also has ImportProduct class. I have used rest controller to call the service on tomcat server. I am passing json data in the request body while calling the service. I am getting SUCCESS response but the rules don’t seem have any effect on the data. For example, if the status != ‘OK’, it should delete that object but it’s not getting deleted. The curl POST request gives back all data that I passed.
I didn’t use out identifier. I think the rule capability is not enabled as shown in the log below:
17:55:35.116 [main] DEBUG org.kie.server.client.impl.KieServicesClientImpl – Supported capabilities by the server: [KieServer, BRM, BPM, CaseMgmt, BPM-UI, BRP, DMN, Swagger]
I fixed the issue. I am trying to sync the github repository so that drools workbench can fetch the updated objects from the repository synced up. I think we can do that by creating a settings.xml file in which we can specify the github repository. I searched a lot on Google but couldn’t find a page where there is a clear way to do that. Please help me achieve that 🙂
Where is the KIE_SERVER_REST_ENDPOINT value fetched from?
LikeLike
It’s passed as environment variable.
KIE_SERVER_REST_ENDPOINT=http://localhost:8180/kie-server/services/rest/server
KIE_SERVER_USER=kieserver
KIE_SERVER_PASSWORD=kieserver1!
LikeLike
Thank you.
LikeLike
I imported your project in drools workbench and deployed it to the KIE server. I can see the container on the deploy page. I have a simple spring boot application which also has ImportProduct class. I have used rest controller to call the service on tomcat server. I am passing json data in the request body while calling the service. I am getting SUCCESS response but the rules don’t seem have any effect on the data. For example, if the status != ‘OK’, it should delete that object but it’s not getting deleted. The curl POST request gives back all data that I passed.
LikeLiked by 1 person
Did you use the out_identifier
“get-objects”: {
“out-identifier”: “import”
}
Also can you confirm that the rule was fired.
“execution-results”: {
“results”: [
{
“value”: 2,
“key”: “firedActivations”
}
],
“facts”: []
Also I recommend to add some logs to the rule.
LikeLike
I didn’t use out identifier. I think the rule capability is not enabled as shown in the log below:
17:55:35.116 [main] DEBUG org.kie.server.client.impl.KieServicesClientImpl – Supported capabilities by the server: [KieServer, BRM, BPM, CaseMgmt, BPM-UI, BRP, DMN, Swagger]
‘{
“type” : “SUCCESS”,
“msg” : “Container ImportProducts_1.0.1-LATEST successfully called.”,
“result” : {
“execution-results” : {
“results” : [ {
“value” : [{“com.test.importproducts.ImportProduct”:{
“id” : “1”,
“category” : “Grocery – Milk”,
“status” : “OK”,
“price” : 25.0
}},{“com.test.importproducts.ImportProduct”:{
“id” : “2”,
“category” : “Fashion – Trouser”,
“status” : “NOT_OK”,
“price” : 1300.0
}},{“com.test.importproducts.ImportProduct”:{
“id” : “3”,
“category” : “Grocery – Wheat”,
“status” : “OK”,
“price” : 425.0
}},{“com.test.importproducts.ImportProduct”:{
“id” : “4”,
“category” : “Grocery – Dairy Milk Chocolate”,
“status” : “OK”,
“price” : 100.0
}}],
“key” : “ImportProduct”
} ],
“facts” : [ {
“value” : {“org.drools.core.common.DefaultFactHandle”:{
“external-form” : “0:1:1934721322:-270083718:1:DEFAULT:NON_TRAIT:java.util.ArrayList”
}},
“key” : “ImportProduct”
} ]
}
}
}’
LikeLike
I think the rule is not getting fired, probably because it is not enabled.
22:11:41.515 [main] DEBUG org.kie.server.client.impl.AbstractKieServicesClientImpl – About to deserialize content:
‘{
“type” : “SUCCESS”,
“msg” : “Container ImportProducts_1.0.1-LATEST successfully called.”,
“result” : {
“execution-results” : {
“results” : [ {
“value” : [{“com.test.importproducts.ImportProduct”:{
“id” : “1”,
“category” : “Grocery – Milk”,
“status” : “OK”,
“price” : 25.0
}},{“com.test.importproducts.ImportProduct”:{
“id” : “2”,
“category” : “Fashion – Trouser”,
“status” : “NOT_OK”,
“price” : 1300.0
}},{“com.test.importproducts.ImportProduct”:{
“id” : “3”,
“category” : “Grocery – Wheat”,
“status” : “OK”,
“price” : 425.0
}},{“com.test.importproducts.ImportProduct”:{
“id” : “4”,
“category” : “Grocery – Dairy Milk Chocolate”,
“status” : “OK”,
“price” : 100.0
}}],
“key” : “ImportProduct”
} ],
“facts” : [ {
“value” : {“org.drools.core.common.DefaultFactHandle”:{
“external-form” : “0:3:459769708:-992461270:3:DEFAULT:NON_TRAIT:java.util.ArrayList”
}},
“key” : “ImportProduct”
} ]
}
}
}’
LikeLike
Hi Sergui,
I fixed the issue. I am trying to sync the github repository so that drools workbench can fetch the updated objects from the repository synced up. I think we can do that by creating a settings.xml file in which we can specify the github repository. I searched a lot on Google but couldn’t find a page where there is a clear way to do that. Please help me achieve that 🙂
Thank you !
LikeLike
Hey did you manage to solve this?
LikeLike
ObjectFilter factsFilter = new ClassObjectFilter(resultClass);
cmds.add(commands.newGetObjects(factsFilter, “Vendor”));
getting factsFilter as null at runtime
LikeLike