One of our most popular Red Hat JBoss BRMS demo's, and one that has been available for quite some time, is the CoolStore demo. The CoolStore demo shows how business rules can be used to calculate values like promotional and shipping discounts in a shopping-cart. It furthermore illustrates concepts like ruleflow-groups and dynamic rule updates using KieScanner.
Rules and micro-services: the JBoss BRMS Decision Server
One of the more interesting features we've recently released in the Red Hat JBoss BRMS 6.x product series is the KIE-Server or the Decision Server. The Desicion Server is a lightweight rules and process runtime that exposes business rules and business processes over both REST and JMS interfaces. This allows applications to easily integrate with JBoss BRMS-based decision logic over a platform independent protocol like REST. The Decision Server provides a "just-enough" runtime environment for rule and process execution, making it fast, lightweight and extremely efficient.
These characteristics make the Decision Server very well suited to run in a containerized and/or PaaS solution. The current trends in application development and deployment all evolve around the concepts of micro-services and containers. JBoss BRMS on Red Hat OpenShift allows us to implement micro-services, that need to provide decision logic, as BRMS rules on our Decision Server, exposing their logic via a RESTful API. One of the fundamental concepts behind micro services is that they're polyglot, i.e. services within a micro-services architecture can be implemented in various languages.
The language in which a particular micro-service is implemented is usually chosen based on available knowledge within the organisation and the given problem domain. And what better platform to choose for implementing decision logic than a rules engine!
Second, the Decision Server runs as a first class citizen in our OpenShift PaaS platform due to its lightweight, just enough, nature. In fact, Red Hat provides a pre-defined OpenShift template and image that you can use to get your rules running in the cloud in no-time. This template allows you to configure an OpenShift Source-2-Image (S2I) build with an existing JBoss BRMS Git-based project. The S2I build will fetch, compile and package the JBoss BRMS project into a KJAR (Knowledge JAR) and deploy it onto the BRMS Decision Server running in a Docker container on the OpenShift platform.
Containers: running your JBoss BRMS micro-service on OpenShift
In order to be able to demonstrate this functionality, we've recently separated the BRMS CoolStore rules repository from the main BRMS CoolStore demo repository. Second, we've updated the rules project to allow it to be compiled an installed in the BRMS Decision Server OpenShift image. We will run you through a series of simple steps that will guide you through installing and running your own CoolStore rules micro-service in a Docker container on a local OpenShift PaaS instance.
- We first need to install an OpenShift instance on our local environment (note that if you have an OpenShift 3 instance already available, you can use that instance). Red Hat provides the Container Development Kit (CDK) that allows you to easily install a local OpenShift 3 installation in a virtual machine. To install the Red Hat CDK, please follow the Getting Started guide or the Installation Manual.
- Once we've installed the CDK, and have our OpenShift instance running, we can create a new project which will contain our BRMS CoolStore micro-service. You can either use the adminstration web-console or the "oc" command-line utility to create this project. In this example we will use the "oc" command to interact with the OpenShift platform. First, login into OpenShift using the "oc login" command and provide a username and password (defaults to u:admin/p:admin). Create a new project with the following command:
oc new-project brms-coolstore --display-name="BRMS CoolStore" --description="Red Hat JBoss BRMS CoolStore micro-services"
The platform will automatically switch to our new project.
- The OpenShift CDK does not contain the required JBoss Middleware ImageStreams out of the box. We first need to install these ImageStreams using a template that can be found here. To install the template (in the openshift namespace), execute the following command:
oc create -f jboss-image-streams.json -n openshift
- The OpenShift CDK does not contain the required JBoss BRMS Decision Server S2I template. Therefore, we first need to install the template. Download the template from the following location. Install the template with the command:
oc create -f decisionserver63-basic-s2i.json
- We will create our CoolStore micro-services application in the project we created in step 2. To create a new application that uses our S2I template, execute the following command:
oc new-app --template=decisionserver63-basic-s2i -p APPLICATION_NAME="coolstore-rules",KIE_SERVER_USER="brmsAdmin",KIE_SERVER_PASSWORD="jbossbrms@01",SOURCE_REPOSITORY_URL="https://github.com/jbossdemocentral/brms-coolstore-repo.git",SOURCE_REPOSITORY_REF=master,KIE_CONTAINER_DEPLOYMENT="CoolStoreRulesContainer=com.redhat:coolstore:2.0.0",CONTEXT_DIR="coolstore"
This "oc" command requires some explanation:
- new-app: indicates that we want to create a new application in the current project.
- --template=decisionserver63-basic-s2i: use the JBoss BRMS Decision Server 6.3 Source-2-Image template
- APPLICATION_NAME: the name of the application
- KIE_SERVER_USER: the username to login to the Decision Server
- KIE_SERVER_PASSWORD: the password to login to the Decision Server
- SOURCE_REPOSITORY_URL: the location of the Git repository that contains our BRMS project (the project containing our rules).
- SOURCE_REPOSITORY_REF: the Git repository's branch to use.
- KIE_CONTAINER_DEPLOYMENT: the name of the KIE Container (in this case CoolStoreRulesContainer) and the Maven GAV (GroupId, ArtifactId and Version) of the KJAR to be deployed in this KIE Container (in this case "com.redhat:coolstore:2.0.0").
- CONTEXT_DIR: the name of the directory in which the S2I image should execute the Maven commands to build the project (KJAR).
More information about these properties can be found here.
When all commands have executed successfully, a CoolStore micro-services container image build should now be running. This can be verified via the "oc" command "oc describe build" which will provide information of the builds defined on the system. To view the log of a certain build, for example build "coolstore-rules-1", we can use the following oc command: "oc logs build/coolstore-rules-1". The initial build can take some time as Maven dependencies need to be downloaded.
When the build has successfully finished, an OpenShift pod running our rules in a Decision Server should now be available. To validate that a Decision Server instance is running, we open the administration console (by default this console is available on https://10.1.2.2:8443/console)and navigate to our "BRMS CoolStore" project. The Overview page shows our Pod with a blue ring with the number 1, indicating that 1 pod is up and running and ready to go (note that the OpenShift platform allows us to easily scale up and down the number of running CoolStore-rules instances/pods by clicking on the "up" and "down" arrows).
We can verify that the Decision Server is running by clicking on the "Service: COOLSTORE-RULES" link. This will bring us to the Decision Server deployment, which will show an empty page. As the Decision Server exposes a RESTful API, not only for rule execution but also for server management, we can inspect the KIE Containers deployed on the Decision Server via the RESTful resource "/kie-server/services/rest/server/containers". So, the full URL in my environment is: http://coolstore-rules-brms-coolstore.rhel-cdk.10.1.2.2.xip.io/kie-server/services/rest/server/containers . You will be prompted for a username and password. Use the values we specified when we created our application, i.e. u:brmsAdmin/p:jbossbrms@01 . The Decision Server will respond with a list of KIE Containers running on the server:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <response type="SUCCESS" msg="List of created containers"> <kie-containers> <kie-container container-id="2e3a25863aa8a502bbeb29a7baf9a637" status="STARTED"> <messages> <content>Container 2e3a25863aa8a502bbeb29a7baf9a637 successfully created with module com.redhat:coolstore:2.0.0.</content> <severity>INFO</severity> <timestamp>2016-09-27T02:58:08.859-04:00</timestamp> </messages> <release-id> <artifact-id>coolstore</artifact-id> <group-id>com.redhat</group-id> <version>2.0.0</version> </release-id> <resolved-release-id> <artifact-id>coolstore</artifact-id> <group-id>com.redhat</group-id> <version>2.0.0</version> </resolved-release-id> </kie-container> </kie-containers> </response>
(Note that for a full overview of the Decision Server's RESTful API, you can open the url http://{host}/kie-server/docs, so in my case http://coolstore-rules-brms-coolstore.rhel-cdk.10.1.2.2.xip.io/kie-server/docs)
We can now do a RESTful call to our CoolStore-Rules micro-service. In this example we will use cURL as our client, but any RESTful client will do. The command inserts a ShoppingCart fact containing a Red Hat Fedora item and a Promotional Event into the rules micro-service. Our rules micro-service will respond with the calculated price as determined by the BRMS rules.
curl -u brmsAdmin:jbossbrms@01 -X POST -H "Accept: application/xml" -H "Content-Type: application/xml" -H "X-KIE-ContentType: XSTREAM" -d '<batch-execution lookup="coolstore-kie-session"><insert out-identifier="outPromo" return-object="false" entry-point="Promo Stream"><com.redhat.coolstore.PromoEvent><itemId>329299</itemId><percentOff>0.25</percentOff></com.redhat.coolstore.PromoEvent></insert><insert out-identifier="shoppingcart" return-object="true" entry-point="DEFAULT"><com.redhat.coolstore.ShoppingCart><cartItemPromoSavings>0.0</cartItemPromoSavings><cartItemTotal>0.0</cartItemTotal><cartTotal>0.0</cartTotal><shippingPromoSavings>0.0</shippingPromoSavings><shippingTotal>0.0</shippingTotal></com.redhat.coolstore.ShoppingCart></insert><insert><com.redhat.coolstore.ShoppingCartItem><itemId>329299</itemId><name>Red Fedora</name><price>34.99</price><promoSavings>0.0</promoSavings><quantity>1</quantity><shoppingCart reference="../../../insert[2]/com.redhat.coolstore.ShoppingCart"/></com.redhat.coolstore.ShoppingCartItem></insert><start-process processId="com.redhat.coolstore.PriceProcess"/><fire-all-rules/></batch-execution>' http://coolstore-rules-brms-coolstore.rhel-cdk.10.1.2.2.xip.io/kie-server/services/rest/server/containers/instances/CoolStoreRulesContainer
Because the inline XML in the cUrl command is a bit hard to read we have printed the formatted XML request below:
<batch-execution lookup="coolstore-kie-session"> <insert out-identifier="outPromo" return-object="false" entry-point="Promo Stream"> <com.redhat.coolstore.PromoEvent> <itemId>329299</itemId> <percentOff>0.25</percentOff> </com.redhat.coolstore.PromoEvent> </insert> <insert out-identifier="shoppingcart" return-object="true" entry-point="DEFAULT"> <com.redhat.coolstore.ShoppingCart> <cartItemPromoSavings>0.0</cartItemPromoSavings> <cartItemTotal>0.0</cartItemTotal> <cartTotal>0.0</cartTotal> <shippingPromoSavings>0.0</shippingPromoSavings> <shippingTotal>0.0</shippingTotal> </com.redhat.coolstore.ShoppingCart> </insert> <insert> <com.redhat.coolstore.ShoppingCartItem> <itemId>329299</itemId> <name>Red Fedora</name> <price>34.99</price> <promoSavings>0.0</promoSavings> <quantity>1</quantity> <shoppingCart reference="../../../insert[2]/com.redhat.coolstore.ShoppingCart"/> </com.redhat.coolstore.ShoppingCartItem> </insert> <start-process processId="com.redhat.coolstore.PriceProcess"/> <fire-all-rules/> </batch-execution>
The response will look like this:
<org.kie.server.api.model.ServiceResponse> <type>SUCCESS</type> <msg>Container 2e3a25863aa8a502bbeb29a7baf9a637 successfully called.</msg> <result class="execution-results"> <result identifier="shoppingcart"> <com.redhat.coolstore.ShoppingCart> <cartItemPromoSavings>-8.7475</cartItemPromoSavings> <cartItemTotal>26.2425</cartItemTotal> <cartTotal>31.2325</cartTotal> <shippingPromoSavings>0.0</shippingPromoSavings> <shippingTotal>4.99</shippingTotal> </com.redhat.coolstore.ShoppingCart> </result> <fact-handle identifier="shoppingcart" external-form="0:2:721203414:721203414:7:DEFAULT:NON_TRAIT:com.redhat.coolstore.ShoppingCart"/> <fact-handle identifier="outPromo" external-form="5:1:2064607180:2064607180:1:Promo Stream:NON_TRAIT:com.redhat.coolstore.PromoEvent"/> </result> </org.kie.server.api.model.ServiceResponse>
The response shows that JBoss BRMS has calculated both the promotional savings, the shipping savings and the total amount of the items in the ShoppingCart. These calculated values can now be used by our application.
Conclusion
The polyglot nature of micro-services architectures enables us to use the right implementation language for the job. And what better language to choose to implement decision logic than the JBoss Business Rules Management System?
The JBoss BRMS Decision Server deployed on the Red Hat OpenShift PaaS platform provides an excellent, lightweight, containerized runtime for rule-based micro-services. In this post we have seen how we can easily build a Docker container running a rules service utilising Red Hat OpenShift's Source-2-Image mechanism, without the need to download, install and configure a Java/JEE server or any other components. By executing 4 simple OpenShift commands we've deployed the rule definitions from an existing JBoss BRMS Git repository onto a highly-available, scalable and high-performant micro-services PaaS runtime. This unique capability makes the combination of Red Hat JBoss BRMS and Red Hat OpenShift an excellent choice for business users and developers that are implementing, or want to implement, decision logic in a highly agile DevOps environment.
About the author:
Duncan Doyle is the Technical Marketing Manager for the JBoss BRMS and BPMSuite platforms at Red Hat. With a background in Red Hat Consulting and Services, Duncan has worked extensively with large Red Hat customers to build advanced, open-source, business-rules and business process management solutions.
He has a strong background in technologies and concepts like Service Oriented Architecture, Continuous Integration & Delivery, rules engines and BPM platforms and is a subject matter expert (SME) on multiple JBoss Middleware technologies, including, but not limited to, JBoss EAP, HornetQ, Fuse, DataGrid, BRMS and BPMSuite. When he’s not working on open-source solutions and technology, he is building Lego with his son and daughter or jamming along some 90’s rock-music on his Fender Stratocaster.