Showing posts with label kie_server. Show all posts
Showing posts with label kie_server. Show all posts

2017/08/17

Maven plugins for KIE Server

Since version 7 of jBPM KIE Server is the only execution server available by default thus it's getting more and more traction. With that in mind there is a need to have it more aligned with CI/CD pipelines to allow simple integration with runtime environments.

To help with that two maven plugins were built:

the main purpose of these plugins is to enable simple deployment (and not only deployment) of kjars into KIE Servers. 
First one is dedicated for unmanaged KIE Servers as that plugin interacts directly with KIE Server REST api. While the second one targets managed KIE Servers as it interacts with KIE Controller (either one in workbench/business central or standalone controller).

These maven plugins can be used to perform deployment of kjar to execution server directly from within a build pipeline. 

Both plugins have comprehensive documentation (see links above) but just for completeness I'd like to list their capabilities in this article:

KIE Server Deploy Maven Plugin

  • deploy -  deploy kjar to runtime environment
  • dispose - dispose running kjar (kie container) in runtime environment
  • update - update version of running kjar (kie container) in runtime environment

KIE Server Controller Deploy Maven Plugin

  • get-template - retrieves existing server templates from controller
  • create-template - creates new server templates with set of containers 
  • delete-template - removes server template
  • get-containers - retrieves containers in given server template
  • get-container - retrieves given container from server template
  • create-container - create new container in given server template
  • delete-container - delete container from given server template
  • start-container - starts container in given server template
  • stop-container - stops container in given server template
  • deploy-container - creates and starts container in given server template
  • dispose-container - stops and removes container from given server template 

    Contribution - a win win situation!

    And now the most important part - these Maven plugins were added by Fabio Massimo as contributions to KIE projects. So I'd like to thank Fabio for his outstanding work and excellent addition to projects. 

    This clearly shows how valuable contributions are! With that I'd like to encourage others to follow Fabio and share with others community members great stuff you all have done or plan to do!


          2017/06/26

          KIE Server welcomes Narayana

          KIE Server (with BPM capabilities) requires data base for persistence. That is well known fact, though to have properly managed persistence there is also need for transaction manager that will ensure consistency of the data jBPM persists.

          Since version 7 KIE Server is the only provided out of the box execution server (there is no execution server in workbench) so it got some additional attention to make sure it does perform in the best possible way.

          KIE Server supports following runtime environments:

          • WildFly 10.x
          • EAP 7.x
          • WebSphere 9
          • WebLogic 12.3
          • Tomcat 8.x

          Since all of the above are supported for jBPM usage they all must provide transaction manager capability. For JEE servers (WildFly, EAP, WebSphere, WebLogic) KIE server relies on what the application server provides. Though for Tomcat the story is slightly different...

          Tomcat does not have transaction manager capabilities so to make use of jBPM/KIE Server on it, it required an external transaction manager to be configured. Until now it was recommended to use bitronix as jBPM test suite was running on it and it does provide integration with Tomcat (plus it covered db connection pooling and JNDI provider for data source look ups). But this has now changed ...

          Starting from jBPM 7.1 KIE Server on Tomcat runs with Narayana, the state of the art transaction manager that nicely integrates with Tomcat and makes the configuration much easier than what was needed with bitronix - and is more native to Tomcat users.

          Before I jump into details on how to configure it on Tomcat, I'd like to take the opportunity and give spacial thanks to:

          Tom Jenkinson and Gytis Trikleris

          for their tremendous help and excellent support while working on this change.

          Installation notes - with BPM capabilities

          Let's see what is actually needed to configure KIE Server on Tomcat with Narayana:
          • (1) Copy following libraries into TOMCAT_HOME/lib
            • javax.security.jacc:javax.security.jacc-api
            • org.kie:kie-tomcat-integration
            • org.slf4j:artifactId=slf4j-api
            • org.slf4j:artifactId=slf4j-jdk14
          • (2) Configure users and roles in tomcat-users.xml (or different user repository if applicable)
          • (3) Configure JACC Valve for security integration Edit TOMCAT_HOME/conf/server.xml and add following in Host section after last Valve declaration 
                   <Valve className="org.kie.integration.tomcat.JACCValve" />
          • (4) Create setenv.sh|bat in TOMCAT_HOME/bin with following content
              CATALINA_OPTS="
              -Djbpm.tsr.jndi.lookup=java:comp/env/TransactionSynchronizationRegistry 
              -Dorg.kie.server.persistence.ds=java:comp/env/jdbc/jbpm 
              -Djbpm.tm.jndi.lookup=java:comp/env/TransactionManager 
              -Dorg.kie.server.persistence.tm=JBossTS 
              -Dhibernate.connection.release_mode=after_transaction 
              -Dorg.kie.server.id=tomcat-kieserver 
              -Dorg.kie.server.location=http://localhost:8080/kie-server/services/rest/server 
              -Dorg.kie.server.controller=http://localhost:8080/kie-wb/rest/controller
              "
                 Items marked in green are related to persistence and transaction.
                 Items marked in blue are general KIE Server parameters needed when running in managed mode.
          • (5) Copy JDBC driver jar into TOMCAT_HOME/lib depending on the data base of your choice
          • (6) Configure data source for jBPM extension of KIE Server 
                     Edit TOMCAT_HOME/conf/context.xml and add following within Context tags of the file:
               <Resource 
                     name="sharedDataSource" 
                     auth="Container" 
                     type="org.h2.jdbcx.JdbcDataSource" 
                     user="sa" 
                     password="sa"
                     url="jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MVCC=TRUE" 
                     description="H2 Data Source" 
                     loginTimeout="0" 
                     testOnBorrow="false"
                     factory="org.h2.jdbcx.JdbcDataSourceFactory"/>
                     This is only an example to use H2 as data base, for other data bases look at
                     Tomcat's configurations docs.

                     Once important note, please keep the name of the data source as sharedDataSource

          • (7) Last but not least is to configure XA recovery 
          • Create xa recovery file next to the context.xml with data base configuration with following content: 
            <?xml version="1.0" encoding="UTF-8"?> 
            <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> 
            <properties> 
              <entry key="DB_1_DatabaseUser">sa</entry> 
              <entry key="DB_1_DatabasePassword">sa</entry> 
              <entry key="DB_1_DatabaseDynamicClass"></entry> 
              <entry key="DB_1_DatabaseURL">java:comp/env/h2DataSource</entry> 
            </properties> 

            Append to CATALINA_OPTS in setenv.sh|bat file following: 
              -Dcom.arjuna.ats.jta.recovery.XAResourceRecovery1= \
              com.arjuna.ats.internal.jdbc.recovery.BasicXARecovery\;
              abs://$CATALINA_HOME/conf/xa-recovery-properties.xml\ \;1
            BasicXARecovery supports following parameters: 
            • path to the properties file 
            • the number of connections defined in the properties file


          Installation notes - without BPM capabilities

          In case you want to use KIE Server without BPM capabilities - for instance for Rules or Planning - then you can completely skip steps from 4 (in step 4 use only the marked in blue items) and still run KIE Server on Tomcat.

          With that, I'd like to say welcome to Narayana in KIE Server - well done!

          2016/08/10

          KIE Server (jBPM extension) brings document support

          Another article for KIE Server series ... and what's coming in version 7. This time around documents and their use in business processes.

          Business processes quite frequently need collaboration around documents (in any meaning of it), thus is it important to allow users to upload and download documents. jBPM provided documents support in version 6 already though it was not exposed on KIE Server for remote interaction.

          jBPM 7 will come with support for documents in KIE Server - that covers both use within process context and outside - direct interaction with underlying document storage.


          jBPM and documents

          To recap quickly how document support is provided by jBPM

          Documents are considered process variables, as such they are applicable for the pluggable persistence strategies defined. Persistence strategies allow to provide various backend storage for process variables, instead of always be put together with process instance into jBPM data base.

          Document is represented by org.jbpm.document.service.impl.DocumentImpl type and comes with dedicated marshaling strategy to deal with this type of variables org.jbpm.document.marshalling.DocumentMarshallingStrategy. In turn marshaling strategy relies on org.jbpm.document.service.DocumentStorageService that is an implementation specific to document storage of your choice. jBPM comes with out of the box implementation of the storage service that simply uses file system as underlying storage system.
          Users can implement alternative DocumentStorageService to provide any kind of storage like data base, ECM etc.

          KIE Server in version 7, provides full support for described above usage - including pluggable DocumentStorageService implementations - and it extends it bit more. It provides REST api on top of org.jbpm.document.service.DocumentStorageService to allow easy access to underlying documents without a need to always go over process instance variables, though it still allows to access documents from within process instance.

          KIE Server provides following endpoints to deal with documents:

          • list documents - GET - http://host:port/kie-server/services/rest/server/documents
            • accept page and pageSize as query parameters to control paging
          • create document - POST - http://host:port/kie-server/services/rest/server/documents
            • DocumentInstance representation in one of supported format (JSON, JAXB, XStream)
          • delete document - DELETE - http://host:port/kie-server/services/rest/server/documents/{DOC_ID}
          • get document (including content) - GET - http://host:port/kie-server/services/rest/server/documents/{DOC_ID}
          • update document - PUT - http://host:port/kie-server/services/rest/server/documents
            • DocumentInstance representation in one of supported format (JSON, JAXB, XStream)
          • get content - GET - http://host:port/kie-server/services/rest/server/documents/{DOC_ID}/content

          NOTE: Same operations are also supported over JMS.

          Documents in action

          Let's see this in action, by just going over very simple use case:
          • Deploy translations project (that is part of jbpm-playground repository) to KIE Server
          • Create new translation process instance from workbench
          • Create new translation process instance from JavaScript client - simple web page
          • Download and remove documents from JavaScript client



          As it can be seen in above screencast, there is smooth integration between workbench, kie server and JavaScript client. Even more is that kie server accept all the data over single endpoint - no separate upload of the document and then start of the process. 

          Important note - be really cautious when using delete operation via KIE Server documents endpoint as it remove document completely meaning there will be no access to it from process instance (as presented in the screencast), moreover process instance won't be aware of it as it considers document storage as an external system.

          Sample source

          For those how would like to try it out themselves, here is a JavaScript client (a simple web page) that was used for the example screencast. Please make sure you drop it on kie server instance to not run into CORS related issues.

          <html>
          <head>
          <title>Send document to KIE Server</title>
          <style type="text/css">
          table.gridtable {
           font-family: verdana,arial,sans-serif;
           font-size:11px;
           color:#333333;
           border-width: 1px;
           border-color: #666666;
           border-collapse: collapse;
          }
          table.gridtable th {
           border-width: 1px;
           padding: 8px;
           border-style: solid;
           border-color: #666666;
           background-color: #dedede;
          }
          table.gridtable td {
           border-width: 1px;
           padding: 8px;
           border-style: solid;
           border-color: #666666;
           background-color: #ffffff;
          }
          </style>
          
          
          <script type='text/javascript'>
            var user = "";
            var pwd = "";
            var startTransalationProcessURL = "http://localhost:8230/kie-server/services/rest/server/containers/translations/processes/translations/instances";
            var documentsURL = "http://localhost:8230/kie-server/services/rest/server/documents";
          
            var srcData = null;
            var fileName = null;
            var fileSize = null;
            function encodeImageFileAsURL() {
          
              var filesSelected = document.getElementById("inputFileToLoad").files;
              if (filesSelected.length > 0) {
                var fileToLoad = filesSelected[0];
                fileName = fileToLoad.name;
                fileSize = fileToLoad.size;
                var fileReader = new FileReader();
          
                fileReader.onload = function(fileLoadedEvent) {
                  var local = fileLoadedEvent.target.result; // <--- data: base64
                  srcData = local.replace(/^data:.*\/.*;base64,/, "");
          
          
                  console.log("Converted Base64 version is " + srcData);
                }
                fileReader.readAsDataURL(fileToLoad);
              } else {
                alert("Please select a file");
              }
            }
          
            function startTransalationProcess() {
              var xhr = new XMLHttpRequest();
              xhr.open('POST', startTransalationProcessURL);
              xhr.setRequestHeader('Content-Type', 'application/json');
              xhr.setRequestHeader ("Authorization", "Basic " + btoa(user + ":" + pwd));
              xhr.onreadystatechange = function () {
                  if (xhr.readyState == 4 && xhr.status == 201) {
                      loadDocuments();
                  }
              }
              var uniqueId = generateUUID();
              xhr.send('{' +
                '"uploader_name" : " '+ document.getElementById("inputName").value +'",' +
                '"uploader_mail" : " '+ document.getElementById("inputEmail").value +'", ' +
                '"original_document" : {"DocumentImpl":{"identifier":"'+uniqueId+'","name":"'+fileName+'","link":"'+uniqueId+'","size":'+fileSize+',"lastModified":'+Date.now()+',"content":"' + srcData + '","attributes":null}}}');
            }
          
          
              function deleteDoc(docId) {
                var xhr = new XMLHttpRequest();
                xhr.open('DELETE', documentsURL +"/" + docId);
                xhr.setRequestHeader('Content-Type', 'application/json');
                xhr.setRequestHeader ("Authorization", "Basic " + btoa(user + ":" + pwd));
                xhr.onreadystatechange = function () {
                    if (xhr.readyState == 4 && xhr.status == 204) {
                      loadDocuments();
                    }
                }
          
                xhr.send();
              }
          
            function loadDocuments() {
              var xhr = new XMLHttpRequest();
              xhr.open('GET', documentsURL);
              xhr.setRequestHeader('Content-Type', 'application/json');
              xhr.setRequestHeader ("Authorization", "Basic " + btoa(user + ":" + pwd));
              xhr.onreadystatechange = function () {
                  if (xhr.readyState == 4 && xhr.status == 200) {
                    var divContainer = document.getElementById("docs");
                    divContainer.innerHTML = "";
                    var documentListJSON = JSON.parse(xhr.responseText);
                    var documentsJSON = documentListJSON['document-instances'];
                    if (documentsJSON.length == 0) {
                      return;
                    }
                    var col = [];
                    for (var i = 0; i < documentsJSON.length; i++) {
                        for (var key in documentsJSON[i]) {
                            if (col.indexOf(key) === -1) {
                                col.push(key);
                            }
                        }
                    }
                    var table = document.createElement("table");
                    table.classList.add("gridtable");
          
                    var tr = table.insertRow(-1);                   
          
                    for (var i = 0; i < col.length; i++) {
                        var th = document.createElement("th");      
                        th.innerHTML = col[i];
                        tr.appendChild(th);
                    }
                    var downloadth = document.createElement("th");
                    downloadth.innerHTML = 'Download';
                    tr.appendChild(downloadth);
                    var deleteth = document.createElement("th");
                    deleteth.innerHTML = 'Delete';
                    tr.appendChild(deleteth);
          
                    for (var i = 0; i < documentsJSON.length; i++) {
          
                        tr = table.insertRow(-1);
          
                        for (var j = 0; j < col.length; j++) {
                            var tabCell = tr.insertCell(-1);
                            tabCell.innerHTML = documentsJSON[i][col[j]];
                        }
                        var tabCellGet = tr.insertCell(-1);
                        tabCellGet.innerHTML = '<button id="button" onclick="window.open(\'' + documentsURL +'/'+documentsJSON[i]['document-id']+'/content\')">Download</button>';
          
                        var tabCellDelete = tr.insertCell(-1);
                        tabCellDelete.innerHTML = '<button id="button" onclick="deleteDoc(\''+documentsJSON[i]['document-id']+'\')">Delete</button>';
                    }
          
                    divContainer.appendChild(table);
                  }
              }
          
              xhr.send();
            }
          
          
            function generateUUID() {
              var d = new Date().getTime();
              var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                  var r = (d + Math.random()*16)%16 | 0;
                  d = Math.floor(d/16);
                  return (c=='x' ? r : (r&0x3|0x8)).toString(16);
              });
              return uuid;
            }
          </script>
          </head>
          <body>
            <h2>Start transalation process</h2>
            Name: <input name="name" type="text" id="inputName"/><br/><br/>
            Email: <input name="email" type="text" id="inputEmail"/><br/><br/>
            Document to translate: <input id="inputFileToLoad" type="file" onchange="encodeImageFileAsURL();" /><br/><br/>
            <input name="send" type="submit" onclick="startTransalationProcess();" /><br/><br/>
          <hr/>
            <h2>Available documents</h2>
            <button id="button" onclick="loadDocuments()">Load documents!</button>
            <div id="docs">
          
            </div>
          </body>
          </html>
          

          And as usual, share your feedback as that is the best way to get improvements that are important to you.

          2016/03/21

          Community extension to KIE Server - welcome Apache Thrift

          In previous articles about KIE Server I described how it can be extended to bring in more features to it, starting with enhanced REST endpoints, through building addition transport layers, and finishing at building custom kie server client implementations.

          It didn't take long and we got official confirmation that it works!!!

          Maurice Betzel, has done excellent job and implemented KIE Server extensions that brings in Apache Thrift into the picture. That allowed him to bridge the gap between Java and PHP to make use of rule evaluation using KIE Server.

          KIE Server with Apache Thrift


          I'd like to encourage every one to look at detailed description about Maurice's work and take it for a spin to see how powerful it is.

          All the credit goes to Maurice and I'd like to thank you as well for keeping me in the loop and verifying extensions mechanism of KIE Server in real life.

          2016/03/02

          Are you ready to dive into (wildfly) swarm?

          KIE Server is a lightweight execution server that comes with various capabilities where out of the box are following:

          • BRM - rules execution (Drools)
          • BPM - business process execution, task management, background jobs (jBPM)
          • BPM-UI - visualize your bpm components on runtime such as process definition and instance (since 6.4)
          • BRP - business resource planning (Optaplanner) (since 6.4)
          It's by default packaged as JEE application (web archive) and deployed to various containers, such as:
          • JBoss EAP
          • Wildfly
          • Tomcat
          • WebLogic
          • WebSphere
          While all this is already quite nice coverage, we don't stay idle and do work on bringing more to you. Let's see what's coming next...

          All the hype about micro service is bringing in tons of new stuff that allows alternative approach for packaging and deployment of our systems or services if you like. Taking into consideration what capabilities KIE Server comes with it would be a crime to not take advantage of it to start building micro services with it. Instead of rewriting all the stuff in different way.


          It's time to introduce Wildfly Swarm (to those that haven't heard about it yet) ...


          Swarm offers an innovative approach to packaging and running JavaEE applications by packaging them with just enough of the platform to "java -jar" your application
          So what Wildfly Swarm means in context of KIE Server?

          Actually it means a lot:

          • first of all it allows us to build executable jars that will bring in KIE Server capabilities to simple java -jar way of working with all it's power!
          • next you can have a "executable kjar" just by starting it with argument that identifies kjar to be available for execution (Group Artifact Version)
          • you can still run in managed mode - connected to controller and managed from within controller but without a need to provision your application server

          With this in mind let's take a look at how to use it with Wildfly Swarm.

          • Clone this repository kie-server-swarm into your local environment.
          • Build the project with maven (mvn clean package)
            • Make sure you run it with latest Maven otherwise you might run into build errors - I tested it with 3.3.9 so it works certainly with it
          • Once it's successfully build you'll find following file inside the target folder
            • kie-server-swarm-1.0-swarm.jar
          • Now you're ready to rock with KIE Server on Wildfly Swarm

          but before we start our KIE Server on Swarm, let's look at what options we have for the project we just built. This project, same as KIE Server, is modularized and allows us to pick only the things we are interested with. While KIE Server allows to disable extensions on runtime (via system properties) sometimes it does not make sense to bring in lots of dependencies if they are not going to be used.

          So you can build the project with following profiles:
          • BRM - includes BRM capability of the KIE Server that allows rules execution only
            • no server components besides REST is configured
            • build it with - mvn clean package -PBRM
          • BPM - includes both BRM and BPM capabilities of the KIE Server - this is the default profile
            • configures Swarm to have transactions and data sources enabled
            • build it with - mvn clean package -PBPM or mvn clean package
          So why it's important to have it done as profiles? It's because the size of resulting file (executable jar) will be smaller. Moreover it reduces number of things Swarm is going to configure and boot when we start our system. So keep this in mind as it might become handy one day or another :)

          Let's get our hands dirty with running KIE Server on Wildfly Swarm


          First thing, let's just start empty server that will let us manage it manually - creating containers, running rules and processes via REST api

          Make sure you're in the project folder (where you executed maven build) and then simply run this command:

          java -Dorg.kie.server.id=swarm-kie-server -Dorg.kie.server.location=http://localhost:8380/server -Dswarm.port.offset=300 -jar target/kie-server-swarm-1.0-swarm.jar
          


          Wait for a while to boot Wildfly Swarm and KIE Server on it. Once it's completed you should be able to access it at http://localhost:8380/server

          NOTE: since KIE Server requires authentication, whenever you attempt to access its REST endpoints you need to logon - by default you should be able to logon with kieserver/kieserver1!
          you can customize users and roles by editing following files:
          kie-server-swarm/src/main/config/security/application-users.properties
          kie-server-swarm/src/main/config/security/application-roles.properties

          Now let's examine a bit what all these parameters mean:

          •  -Dorg.kie.server.id=swarm-kie-server - specifies the unique identifier of the kie server - it is important when running in managed mode but good to use it always to make it a habit
          • -Dorg.kie.server.location=http://localhost:8380/server - specifies the actual location where our KIE Server is going to be available - this must be a direct URL to actual instance even it if's behind load balancer - again important when running in managed mode
          • -Dswarm.port.offset=300  - sets global port offset to avoid port conflicts when running many instances of wildfly on same machine

          Next, let's run our first executable KJAR... to do so we just extend the command from first run and add arguments to the execution

          java -Dorg.kie.server.id=swarm-kie-server -Dorg.kie.server.location=http://localhost:8380/server -jar target/kie-server-swarm-1.0-swarm.jar org.jbpm:HR:1.0
          


          as you can see the only difference is:
          org.jbpm:HR:1.0
          which is GAV of a KJAR that is going to be deployed upon start of KIE Server on Swarm. So with just single command line we have fully functional server with BPM capabilities and HR project deployed to it.

          Last but not least, let's run it in fully managed way - with controller.
          Before you start wildfly Swarm with KIE Server, make sure you start controller (KIE workbench) so you'll see how nicely it registers automatically upon start.

          Once controller (workbench) is running issue following command:

          java -Dorg.kie.server.id=swarm-kie-server -Dorg.kie.server.location=http://localhost:8380/server -Dorg.kie.server.controller=http://localhost:8080/kie-wb/rest/controller -jar target/kie-server-swarm-1.0-swarm.jar
          


          Again, a singe parameter difference between the first command we used to start empty KIE Server on Swarm - in this case it's controller url:
          • -Dorg.kie.server.controller=http://localhost:8080/kie-wb/rest/controller
          Make sure that this URL matches your controller being deployed - it can differer in terms of

          • host (localhost in this case)
          • port (8080 in this case)
          • context root (kie-wb in this case)
          Now you're ready to rock with Wildfly Swarm and KIE Server to build your own micro services backed by business knowledge.

          Enjoy your dive into Swarm and as usual comments are more than welcome.

          2015/12/03

          KIE Server: Extend KIE Server client with new capabilities

          Last but not least part of KIE Server extensions is about extending KIE Server Client with additional capabilities.

          Use case

          On top of what was built in second article (adding Mina transport to KIE Server), we need to add KIE Server Client extension that allow to use Mina transport with unified KIE Server Client API.

          Before you start create empty maven project (packaging jar) with following dependencies:

          <properties>
              <version.org.kie>6.4.0-SNAPSHOT</version.org.kie>
            </properties>
          
            <dependencies>
              <dependency>
                <groupId>org.kie.server</groupId>
                <artifactId>kie-server-api</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
          
              <dependency>
                <groupId>org.kie.server</groupId>
                <artifactId>kie-server-client</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
              
              <dependency>
                <groupId>org.drools</groupId>
                <artifactId>drools-compiler</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
            </dependencies>
          

          Design ServicesClient API interface

          First thing we need to do is to decide what API we should have to be exposed to the callers of our Client API. Since the Mina extension is an extension on top of Drools one so let's provide same capabilities as RulesServicesClient:

          public interface RulesMinaServicesClient extends RuleServicesClient {
          
          }
          

          As you can notice it simply extends the default RulesServiceClient interface and thus provide same capabilities. 

          Why we need to have additional interface for it? It's because we are going to register client implementations based on their interface and there can be only one implementation for given interface.

          Implement RulesMinaServicesClient

          Next step is to actually implement the client and here we are going to prepare a socket based communication for simplicity sake. We could use Apache Mina client API though this would introduce additional dependency which we don't need for sample implementation.

          Note that this client implementation is very simple and in many cases can be improved, but the point here is to show how it can be implemented rather than provide bullet proof code.

          So few aspects to remember when reviewing the implementation:
          • it relies on default configuration from KIE Server client and thus uses serverUrl as place where to provide host and port of Mina server
          • hardcodes JSON as marshaling format
          • decision if the response is success or failure is based on checking if the received message is a JSON object (start with {) - very simple though works for simple cases
          • uses direct socket communication with blocking api while waiting for first line of the response and then reads up all lines that are available
          • does not use "stream mode" meaning it disconnects from the server after invoking command
          Here is the implementation
          public class RulesMinaServicesClientImpl implements RulesMinaServicesClient {
              
              private String host;
              private Integer port;
              
              private Marshaller marshaller;
              
              public RulesMinaServicesClientImpl(KieServicesConfiguration configuration, ClassLoader classloader) {
                  String[] serverDetails = configuration.getServerUrl().split(":");
                  
                  this.host = serverDetails[0];
                  this.port = Integer.parseInt(serverDetails[1]);
                  
                  this.marshaller = MarshallerFactory.getMarshaller(configuration.getExtraJaxbClasses(), MarshallingFormat.JSON, classloader);
              }
          
              public ServiceResponse<String> executeCommands(String id, String payload) {
                  
                  try {
                      String response = sendReceive(id, payload);
                      if (response.startsWith("{")) {
                          return new ServiceResponse<String>(ResponseType.SUCCESS, null, response);
                      } else {
                          return new ServiceResponse<String>(ResponseType.FAILURE, response);
                      }
                  } catch (Exception e) {
                      throw new KieServicesException("Unable to send request to KIE Server", e);
                  }
              }
          
              public ServiceResponse<String> executeCommands(String id, Command<?> cmd) {
                  try {
                      String response = sendReceive(id, marshaller.marshall(cmd));
                      if (response.startsWith("{")) {
                          return new ServiceResponse<String>(ResponseType.SUCCESS, null, response);
                      } else {
                          return new ServiceResponse<String>(ResponseType.FAILURE, response);
                      }
                  } catch (Exception e) {
                      throw new KieServicesException("Unable to send request to KIE Server", e);
                  }
              }
          
              protected String sendReceive(String containerId, String content) throws Exception {
                  
                  // content - flatten the content to be single line
                  content = content.replaceAll("\\n", "");
                  
                  Socket minaSocket = null;
                  PrintWriter out = null;
                  BufferedReader in = null;
          
                  StringBuffer data = new StringBuffer();
                  try {
                      minaSocket = new Socket(host, port);
                      out = new PrintWriter(minaSocket.getOutputStream(), true);
                      in = new BufferedReader(new InputStreamReader(minaSocket.getInputStream()));
                  
                      // prepare and send data
                      out.println(containerId + "|" + content);
                      // wait for the first line
                      data.append(in.readLine());
                      // and then continue as long as it's available
                      while (in.ready()) {
                          data.append(in.readLine());
                      }
                      
                      return data.toString();
                  } finally {
                      out.close();
                      in.close();
                      minaSocket.close();
                  }
              }
          }
          

          Once we have the client interface and client implementation we need to make it available for KIE Service client to find it.

          Implement KieServicesClientBuilder

          org.kie.server.client.helper.KieServicesClientBuilder is the glue interface that allows to provide additional client apis to generic KIE Server Client infrastructure. This interface have two methods:
          • getImplementedCapability - which must much the server capability (extension) is going to use
          • build - which is responsible for providing map of client implementations where key is the interface and value fully initialized implementation
          Here is a simple implementation of the client builder for this use case

          public class MinaClientBuilderImpl implements KieServicesClientBuilder {
          
              public String getImplementedCapability() {
                  return "BRM-Mina";
              }
          
              public Map<Class<?>, Object> build(KieServicesConfiguration configuration, ClassLoader classLoader) {
                  Map<Class<?>, Object> services = new HashMap<Class<?>, Object>();
          
                  services.put(RulesMinaServicesClient.class, new RulesMinaServicesClientImpl(configuration, classLoader));
          
                  return services;
              }
          
          }
          

          Make it discoverable

          Same story as for other extensions ... once we have all that needs to be implemented, it's time to make it discoverable so KIE Server Client can find and register this extension on runtime. Since KIE Server  Client is based on Java SE ServiceLoader mechanism we need to add one file into our extension jar file:

          META-INF/services/org.kie.server.client.helper.KieServicesClientBuilder

          And the content of this file is a single line that represents fully qualified class name of our custom implementation of  KieServicesClientBuilder.


          How to use it

          The usage scenario does not much differ from regular KIE Server Client use case:
          • create client configuration
          • create client instance
          • get service client by type
          • invoke client methods
          Here is implementation that create KIE Server Client for RulesMinaServiceClient

          protected RulesMinaServicesClient buildClient() {
              KieServicesConfiguration configuration = KieServicesFactory.newRestConfiguration("localhost:9123", null, null);
              List<String> capabilities = new ArrayList<String>();
              // we need to add explicitly capabilities as the mina client does not respond to get server info requests.
              capabilities.add("BRM-Mina");
              
              configuration.setCapabilities(capabilities);
              configuration.setMarshallingFormat(MarshallingFormat.JSON);
              
              configuration.addJaxbClasses(extraClasses);
              
              KieServicesClient kieServicesClient =  KieServicesFactory.newKieServicesClient(configuration);
              
              RulesMinaServicesClient rulesClient = kieServicesClient.getServicesClient(RulesMinaServicesClient.class);
              
              return rulesClient;
          }
          
          And here is how it is used to invoke operations on KIE Server via Mina transport

          RulesMinaServicesClient rulesClient = buildClient();
          
          List<Command<?>> commands = new ArrayList<Command<?>>();
          BatchExecutionCommand executionCommand = commandsFactory.newBatchExecution(commands, "defaultKieSession");
          
          Person person = new Person();
          person.setName("mary");
          commands.add(commandsFactory.newInsert(person, "person"));
          commands.add(commandsFactory.newFireAllRules("fired"));
          
          ServiceResponse<String> response = rulesClient.executeCommands(containerId, executionCommand);
          Assert.assertNotNull(response);
          
          Assert.assertEquals(ResponseType.SUCCESS, response.getType());
          
          String data = response.getResult();
          
          Marshaller marshaller = MarshallerFactory.getMarshaller(extraClasses, MarshallingFormat.JSON, this.getClass().getClassLoader());
          
          ExecutionResultImpl results = marshaller.unmarshall(data, ExecutionResultImpl.class);
          Assert.assertNotNull(results);
          
          Object personResult = results.getValue("person");
          Assert.assertTrue(personResult instanceof Person);
          
          Assert.assertEquals("mary", ((Person) personResult).getName());
          Assert.assertEquals("JBoss Community", ((Person) personResult).getAddress());
          Assert.assertEquals(true, ((Person) personResult).isRegistered());
          

          Complete code of this client extension can be found here.

          And that's the last extension method to provide more features in KIE Server then given out of the box.

          Thanks for reading the entire series of KIE Server extensions and any and all feedback welcome :)

          KIE Server: Extend KIE Server with additional transport

          There might be some cases where existing transports in KIE Server won't be sufficient, for whatever reason

          • not fast enough
          • difficult to deal with string based data formats (JSON, XML)
          • you name it..so there might be a need to build a custom transport to overcome this limitation.

          Use case

          Add additional transport to KIE Server that allows to use Drools capabilities. For this example we will use Apache Mina as underlying transport framework and we're going to exchange string based data that will still rely on existing marshaling operations. For simplicity reason we support only JSON format.

          Before you start create empty maven project (packaging jar) with following dependencies:

          <properties>
              <version.org.kie>6.4.0-SNAPSHOT</version.org.kie>
            </properties>
          
            <dependencies>
              <dependency>
                <groupId>org.kie</groupId>
                <artifactId>kie-api</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
              <dependency>
                <groupId>org.kie</groupId>
                <artifactId>kie-internal</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
          
              <dependency>
                <groupId>org.kie.server</groupId>
                <artifactId>kie-server-api</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
              <dependency>
                <groupId>org.kie.server</groupId>
                <artifactId>kie-server-services-common</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
              <dependency>
                <groupId>org.kie.server</groupId>
                <artifactId>kie-server-services-drools</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
          
              <dependency>
                <groupId>org.drools</groupId>
                <artifactId>drools-core</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
              <dependency>
                <groupId>org.drools</groupId>
                <artifactId>drools-compiler</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
              <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.2</version>
              </dependency>
          
              <dependency>
                <groupId>org.apache.mina</groupId>
                <artifactId>mina-core</artifactId>
                <version>2.0.9</version>
              </dependency>
          
            </dependencies>
          

          Implement KieServerExtension

          Main part of this implementation is done by implementing org.kie.server.services.api.KieServerExtension which is KIE Server extension main interface. This interface has number of methods which implementation depends on the actual needs:

          In our case we don't need to do anything when container is created or disposed as we simply extend the Drools extension and rely on complete setup in that component. For this example we are mostly interested in implementing:
          • init method
          • destroy method
          in these two methods we are going to manage life cycle of the Apache Mina server. 
          public interface KieServerExtension {
          
              boolean isActive();
          
              void init(KieServerImpl kieServer, KieServerRegistry registry);
          
              void destroy(KieServerImpl kieServer, KieServerRegistry registry);
          
              void createContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters);
          
              void disposeContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters);
          
              List<Object> getAppComponents(SupportedTransports type);
          
              <T> T getAppComponents(Class<T> serviceType);
          
              String getImplementedCapability();
          
              List<Object> getServices();
          
              String getExtensionName();
          
              Integer getStartOrder();
          }
          

          Next there are few methods that describe the extension:
          • getImplementedCapability - should instruct what kind of capability is covered by this extension, note that capability should be unique within KIE Server
          • getExtensionName - human readable name of this extension
          • getStartOrder - defined when given extension should be started, important for extensions that have dependencies to other extensions like in this case where it depends on Drools (startup order is set to 0) so our extension should start after drools one - thus set to 20
          Remaining methods are left with standard implementation to fulfill interface requirements.

          Here is the implementation of the KIE Server extension based on Apache Mina:

          public class MinaDroolsKieServerExtension implements KieServerExtension {
          
              private static final Logger logger = LoggerFactory.getLogger(MinaDroolsKieServerExtension.class);
          
              public static final String EXTENSION_NAME = "Drools-Mina";
          
              private static final Boolean disabled = Boolean.parseBoolean(System.getProperty("org.kie.server.drools-mina.ext.disabled", "false"));
              private static final String MINA_HOST = System.getProperty("org.kie.server.drools-mina.ext.port", "localhost");
              private static final int MINA_PORT = Integer.parseInt(System.getProperty("org.kie.server.drools-mina.ext.port", "9123"));
              
              // taken from dependency - Drools extension
              private KieContainerCommandService batchCommandService;
              
              // mina specific 
              private IoAcceptor acceptor;
              
              public boolean isActive() {
                  return disabled == false;
              }
          
              public void init(KieServerImpl kieServer, KieServerRegistry registry) {
                  
                  KieServerExtension droolsExtension = registry.getServerExtension("Drools");
                  if (droolsExtension == null) {
                      logger.warn("No Drools extension available, quiting...");
                      return;
                  }
                  
                  List<Object> droolsServices = droolsExtension.getServices();
                  for( Object object : droolsServices ) {
                      // in case given service is null (meaning was not configured) continue with next one
                      if (object == null) {
                          continue;
                      }
                      if( KieContainerCommandService.class.isAssignableFrom(object.getClass()) ) {
                          batchCommandService = (KieContainerCommandService) object;
                          continue;
                      } 
                  }
                  if (batchCommandService != null) {
                      acceptor = new NioSocketAcceptor();
                      acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
              
                      acceptor.setHandler( new TextBasedIoHandlerAdapter(batchCommandService) );
                      acceptor.getSessionConfig().setReadBufferSize( 2048 );
                      acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
                      try {
                          acceptor.bind( new InetSocketAddress(MINA_HOST, MINA_PORT) );
                          
                          logger.info("{} -- Mina server started at {} and port {}", toString(), MINA_HOST, MINA_PORT);
                      } catch (IOException e) {
                          logger.error("Unable to start Mina acceptor due to {}", e.getMessage(), e);
                      }
              
                  }
              }
          
              public void destroy(KieServerImpl kieServer, KieServerRegistry registry) {
                  if (acceptor != null) {
                      acceptor.dispose();
                      acceptor = null;
                  }
                  logger.info("{} -- Mina server stopped", toString());
              }
          
              public void createContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
                  // no op - it's already handled by Drools extension
          
              }
          
              public void disposeContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
                  // no op - it's already handled by Drools extension
          
              }
          
              public List<Object> getAppComponents(SupportedTransports type) {
                  // nothing for supported transports (REST or JMS)
                  return Collections.emptyList();
              }
          
              public <T> T getAppComponents(Class<T> serviceType) {
          
                  return null;
              }
          
              public String getImplementedCapability() {
                  return "BRM-Mina";
              }
          
              public List<Object> getServices() {
                  return Collections.emptyList();
              }
          
              public String getExtensionName() { 
                  return EXTENSION_NAME;
              }
          
              public Integer getStartOrder() {
                  return 20;
              }
          
              @Override
              public String toString() {
                  return EXTENSION_NAME + " KIE Server extension";
              }
          }
          
          As can be noticed main part of implementation is in the init method that is responsible for collecting services from Drools extensions and bootstrapping Apache Mina server.
          Worth noticing is the TextBaseIOHandlerAdapter class that is used as handler on Mina server that in essence will react to incoming requests.

          Implement Apache Mina handler

          Here is the implementation of the handler class that receives text message and executes it on drools service. 

          public class TextBasedIoHandlerAdapter extends IoHandlerAdapter {
              
              private static final Logger logger = LoggerFactory.getLogger(TextBasedIoHandlerAdapter.class);
          
              private KieContainerCommandService batchCommandService;
              
              public TextBasedIoHandlerAdapter(KieContainerCommandService batchCommandService) {
                  this.batchCommandService = batchCommandService;
              }
          
              @Override
              public void messageReceived( IoSession session, Object message ) throws Exception {
                  String completeMessage = message.toString();
                  logger.debug("Received message '{}'", completeMessage);
                  if( completeMessage.trim().equalsIgnoreCase("quit") || completeMessage.trim().equalsIgnoreCase("exit") ) {
                      session.close(false);
                      return;
                  }
          
                  String[] elements = completeMessage.split("\\|");
                  logger.debug("Container id {}", elements[0]);
                  try {
                      ServiceResponse<String> result = batchCommandService.callContainer(elements[0], elements[1], MarshallingFormat.JSON, null);
                      
                      if (result.getType().equals(ServiceResponse.ResponseType.SUCCESS)) {
                          session.write(result.getResult());
                          logger.debug("Successful message written with content '{}'", result.getResult());
                      } else {
                          session.write(result.getMsg());
                          logger.debug("Failure message written with content '{}'", result.getMsg()); 
                      }
                  } catch (Exception e) {
                      
                  }
              }
          }
          

          Few details about the handler implementation:
          • each incoming request is single line, so make sure before submitting anything to it make sure it's single line
          • there is a need to pass container id in this single line so this handler expects following format:
            • containerID|payload
          • response is set the way it is produced by marshaller and that can be multiple lines
          • handlers allows "stream mode" that allows to send commands without disconnecting from KIE Server session. to be able to quit the stream mode - send either exit or quit

          Make it discoverable

          Same story as for REST extension ... once we have all that needs to be implemented, it's time to make it discoverable so KIE Server can find and register this extension on runtime. Since KIE Server is based on Java SE ServiceLoader mechanism we need to add one file into our extension jar file:

          META-INF/services/org.kie.server.services.api.KieServerExtension

          And the content of this file is a single line that represents fully qualified class name of our custom implementation of  KieServerExtension.


          Last step is to build this project (which will result in jar file) and copy the result into:
           kie-server.war/WEB-INF/lib

          Since this extension depends on Apache Mina we need to copy mina-core-2.0.9.jar into  kie-server.war/WEB-INF/lib as well.

          Usage example

          Clone this repository and build the kie-server-demo project. Once you build it you will be able to deploy it to KIE Server (either directly using KIE Server management REST api) or via KIE workbench controller.

          Once deployed and KIE Server started you should find in logs that new KIE Server extension started:
          Drools-Mina KIE Server extension -- Mina server started at localhost and port 9123
          Drools-Mina KIE Server extension has been successfully registered as server extension

          That means we are now interact with our Apache Mina based transport in KIE Server. So let's give it a go... we could write a code to interact with Mina server but to avoid another coding exercise let's use... wait for it .... telnet :)

          Start telnet and connect to KIE Server on port 9123:
          telnet 127.0.0.1 9123

          once connected you can easily interact with alive and kicking KIE Server:
          Trying 127.0.0.1...
          Connected to localhost.
          Escape character is '^]'.
          demo|{"lookup":"defaultKieSession","commands":[{"insert":{"object":{"org.jbpm.test.Person":{"name":"john","age":25}}}},{"fire-all-rules":""}]}
          {
            "results" : [ {
              "key" : "",
              "value" : 1
            } ],
            "facts" : [ ]
          }
          demo|{"lookup":"defaultKieSession","commands":[{"insert":{"object":{"org.jbpm.test.Person":{"name":"john","age":25}}}},{"fire-all-rules":""}]}
          {
            "results" : [ {
              "key" : "",
              "value" : 1
            } ],
            "facts" : [ ]
          }
          demo|{"lookup":"defaultKieSession","commands":[{"insert":{"object":{"org.jbpm.test.Person":{"name":"maciek","age":25}}}},{"fire-all-rules":""}]}
          {
            "results" : [ {
              "key" : "",
              "value" : 1
            } ],
            "facts" : [ ]
          }
          exit
          Connection closed by foreign host.

          where:

          • green is request message
          • blue is response
          • orange is exit message


          in the server side logs you will see something like this:
          16:33:40,206 INFO  [stdout] (NioProcessor-2) Hello john
          16:34:03,877 INFO  [stdout] (NioProcessor-2) Hello john
          16:34:19,800 INFO  [stdout] (NioProcessor-2) Hello maciek

          This illustrated the stream mode where we simply type in commands after command without disconnecting from the KIE Server.

          This concludes this exercise and complete code for this can be found here.

          KIE Server: Extend existing server capability with extra REST endpoint

          First and most likely the most frequently required extension to KIE Server is to extend REST api of already available extension - Drools or jBPM. There are few simple steps that needs to be done to provide extra endpoints in KIE Server.

          Our use case

          We are going to extend Drools extension with additional endpoint that will do very simple thing - expose single endpoint that will accept list of facts to be inserted and automatically call fire all rules and retrieve all objects from ksession.
          Endpoint will be bound to following path:
          server/containers/instances/{id}/ksession/{ksessionId}

          where:
          • id is container identifier
          • ksessionId is name of the ksession within container to be used

          Before you start create empty maven project (packaging jar) with following dependencies:

           
           <properties>
              <version.org.kie>6.4.0-SNAPSHOT</version.org.kie>
            </properties>
          
            <dependencies>
              <dependency>
                <groupId>org.kie</groupId>
                <artifactId>kie-api</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
              <dependency>
                <groupId>org.kie</groupId>
                <artifactId>kie-internal</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
          
              <dependency>
                <groupId>org.kie.server</groupId>
                <artifactId>kie-server-api</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
              <dependency>
                <groupId>org.kie.server</groupId>
                <artifactId>kie-server-services-common</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
              <dependency>
                <groupId>org.kie.server</groupId>
                <artifactId>kie-server-services-drools</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
              
              <dependency>
                <groupId>org.kie.server</groupId>
                <artifactId>kie-server-rest-common</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
          
              <dependency>
                <groupId>org.drools</groupId>
                <artifactId>drools-core</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
              <dependency>
                <groupId>org.drools</groupId>
                <artifactId>drools-compiler</artifactId>
                <version>${version.org.kie}</version>
              </dependency>
              <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.2</version>
              </dependency>
          
            </dependencies>
          

          Implement KieServerApplicationComponentsService

          First step is to implement org.kie.server.services.api.KieServerApplicationComponentsService that is responsible for delivering REST endpoints (aka resources) to the KIE Server infrastructure that will be then deployed on application start. This interface is very simple and has only one method:

          Collection<Object> getAppComponents(String extension, 
                                              SupportedTransports type, Object... services)

          this method is then invoked by KIE Server when booting up and should return all resources that REST container should deploy.

          This method implementation should take into consideration following:

          • it is called by all extensions and thus it provides extension name so custom implementations can decide if this extension is for it or not
          • supported type - either REST or JMS - in our case it will be REST only
          • services - dedicated services to given extensions that can be then used as part of custom extension - usually these are engine services
          Here is a sample implementation that uses Drools extension as base (and by that its services)

           
          public class CusomtDroolsKieServerApplicationComponentsService implements KieServerApplicationComponentsService {
          
              private static final String OWNER_EXTENSION = "Drools";
              
              public Collection<Object> getAppComponents(String extension, SupportedTransports type, Object... services) {
                  // skip calls from other than owning extension
                  if ( !OWNER_EXTENSION.equals(extension) ) {
                      return Collections.emptyList();
                  }
                  
                  RulesExecutionService rulesExecutionService = null;
                  KieServerRegistry context = null;
                 
                  for( Object object : services ) { 
                      if( RulesExecutionService.class.isAssignableFrom(object.getClass()) ) { 
                          rulesExecutionService = (RulesExecutionService) object;
                          continue;
                      } else if( KieServerRegistry.class.isAssignableFrom(object.getClass()) ) {
                          context = (KieServerRegistry) object;
                          continue;
                      }
                  }
                  
                  List<Object> components = new ArrayList<Object>(1);
                  if( SupportedTransports.REST.equals(type) ) {
                      components.add(new CustomResource(rulesExecutionService, context));
                  }
                  
                  return components;
              }
          
          }
          


          So what can be seen here is that it only reacts to Drools extension services and others are ignored. Next it will select RulesExecutionService and KieServerRegistry from available services. Last will create new CustomResource (implemented in next step) and returns it as part of the components list.

          Implement REST resource

          Next step is to implement custom REST resource that will be used by KIE Server to provide additional functionality. Here we do a simple, single method resource that:
          • uses POST http method
          • expects following data to be given:
            • container id as path argument
            • ksession id as path argument
            • list of facts as message payload 
          • supports all KIE Server data formats:
            • XML - JAXB
            • JSON
            • XML - Xstream
          It will then unmarshal the payload into actual List<?> and create for each item in the list new InsertCommand. These inserts will be then followed by FireAllRules and GetObject commands. All will be then added as commands of BatchExecutionCommand and used to call rule engine. As simple as that. It is already available on KIE Server out of the box but requires complete setup of BatchExecutionCommand to be done on client side. Not that it's not possible but this extension is tailored one for simple pattern :
          insert -> evaluate -> return

          Here is how the simple implementation could look like:
           
          @Path("server/containers/instances/{id}/ksession")
          public class CustomResource {
          
              private static final Logger logger = LoggerFactory.getLogger(CustomResource.class);
              
              private KieCommands commandsFactory = KieServices.Factory.get().getCommands();
          
              private RulesExecutionService rulesExecutionService;
              private KieServerRegistry registry;
          
              public CustomResource() {
          
              }
          
              public CustomResource(RulesExecutionService rulesExecutionService, KieServerRegistry registry) {
                  this.rulesExecutionService = rulesExecutionService;
                  this.registry = registry;
              }
              
              @POST
              @Path("/{ksessionId}")
              @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
              @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
              public Response insertFireReturn(@Context HttpHeaders headers, 
                      @PathParam("id") String id, 
                      @PathParam("ksessionId") String ksessionId, 
                      String cmdPayload) {
          
                  Variant v = getVariant(headers);
                  String contentType = getContentType(headers);
                  
                  MarshallingFormat format = MarshallingFormat.fromType(contentType);
                  if (format == null) {
                      format = MarshallingFormat.valueOf(contentType);
                  }
                  try {    
                      KieContainerInstance kci = registry.getContainer(id);
                      
                      Marshaller marshaller = kci.getMarshaller(format);
                      
                      List<?> listOfFacts = marshaller.unmarshall(cmdPayload, List.class);
                      
                      List<Command<?>> commands = new ArrayList<Command<?>>();
                      BatchExecutionCommand executionCommand = commandsFactory.newBatchExecution(commands, ksessionId);
                      
                      for (Object fact : listOfFacts) {
                          commands.add(commandsFactory.newInsert(fact, fact.toString()));
                      }
                      commands.add(commandsFactory.newFireAllRules());
                      commands.add(commandsFactory.newGetObjects());
                          
                      ExecutionResults results = rulesExecutionService.call(kci, executionCommand);
                              
                      String result = marshaller.marshall(results);
                      
                      
                      logger.debug("Returning OK response with content '{}'", result);
                      return createResponse(result, v, Response.Status.OK);
                  } catch (Exception e) {
                      // in case marshalling failed return the call container response to keep backward compatibility
                      String response = "Execution failed with error : " + e.getMessage();
                      logger.debug("Returning Failure response with content '{}'", response);
                      return createResponse(response, v, Response.Status.INTERNAL_SERVER_ERROR);
                  }
          
              }
          }
          


          Make it discoverable

          Once we have all that needs to be implemented, it's time to make it discoverable so KIE Server can find and register this extension on runtime. Since KIE Server is based on Java SE ServiceLoader mechanism we need to add one file into our extension jar file:

          META-INF/services/org.kie.server.services.api.KieServerApplicationComponentsService

          And the content of this file is a single line that represents fully qualified class name of our custom implementation of  KieServerApplicationComponentsService.


          Last step is to build this project (which will result in jar file) and copy the result into:
           kie-server.war/WEB-INF/lib

          And that's all that is needed. Start KIE Server and then you can start interacting with your new REST endpoint that relies on Drools extension.

          Usage example

          Clone this repository and build the kie-server-demo project. Once you build it you will be able to deploy it to KIE Server (either directly using KIE Server management REST api) or via KIE workbench controller.

          Once deployed you can use following to invoke new endpoint:
          URL: 
          http://localhost:8080/kie-server/services/rest/server/containers/instances/demo/ksession/defaultKieSession

          HTTP Method: POST
          Headers:
          Content-Type: application/json
          Accept: application/json

          Message payload:
          [
          {
            "org.jbpm.test.Person":{
               "name":"john",
               "age":25}
             },
            {
              "org.jbpm.test.Person":{
                 "name":"mary",
                 "age":22}
             }
          ]

          A simple list with two items representing people, execute it and you should see following in server log:
          13:37:20,347 INFO  [stdout] (default task-24) Hello mary
          13:37:20,348 INFO  [stdout] (default task-24) Hello john

          And the response should contain objects retrieved after rule evaluation where each Person object has:
          • address set to 'JBoss Community'
          • registered flag set to true

          With this sample use case we illustrated how easy it is to extend REST api of KIE Server. Complete code for this extension can be found here.

          Extending KIE Server capabilities

          As a follow up of previous articles about  KIE Server, I'd like to present the extensibility support provided by KIE Server. Let's quickly look at KIE Server architecture...

          Extensions overview

          KIE Server is built around extensions, every piece of functionality is actually provided by extension. Out of the box we have following:

          • KIE Server extension - this is the default extension that provides management capabilities of the KIE Server - like creating or disposing containers etc
          • Drools extension - this extension provides rules (BRMS) capabilities, e.g. allows to inserting facts and firing rules (among others)
          • jBPM extension - this extensions provides process (BPMS) capabilities e.g. business process execution, user tasks, async jobs
          • jBPM UI extension - added in 6.4 additional extension that depends on jBPM extension and provides UI related capabilities - forms and process images
          With just these out of the box capabilities KIE Server provides quite a bit of coverage. But that not all... extensions provide the capabilities but these capabilities must be somehow exposed to the users. And here KIE Server comes with two transports by default:
          • REST
          • JMS
          Due to a need to be able to effectively manage extensions in runtime these are packaged in different jar files. So looking at the out of the box extensions we have following modules:
          • Drools extension
            • kie-server-services-drools
            • kie-server-rest-drools
          • jBPM extension
            • kie-server-services-jbpm
            • kie-server-rest-jbpm
          • jBPM UI extension
            • kie-server-services-jbpm-ui
            • kie-server-rest-jbpm-ui
          All above modules are automatically discovered on runtime and registered in KIE Server if the are enabled (which by default they are). Extensions can be disabled using system properties
          • Drools extension
            • org.drools.server.ext.disabled = true
          • jBPM extension
            • org.jbpm.server.ext.disabled = true
          • jBPM UI extension
            • org.jbpm.ui.server.ext.disabled = true
          But this is not all... if someone does not like the client api a client api can also be extended by implementing custom interfaces. This is why there is an extra step needed to get remote client:

          kieServerClient.getServicesClient(Interface.class)

          Why extensions are needed?

          Let's not look at why would someone consider extending KIE server?

          • First and foremost is there might be missing functionality which is not yet implemented in KIE Server but exists in engines (process or rule engine). 
            • REST extension
          • Another use case is that something should be done differently than it is done out of the box - different parameters and so on..
            • client extension
          • Last but not least, it should be possible to extend the transport coverage meaning allow users to add other transports next to REST and JMS.
            • server extension
          With this users can first of all, cover their requirements even if the out of the box KIE Server implementation does not provide required functionality. Next such extensions cane contributed to be included in the project or can be shipped as custom extensions available for other users.

          This benefits both project and users so I'd like to encourage every one to look into details and think if there is anything missing and if so try to solve it by building extensions.

          Let's extend KIE Server capabilities

          Following three articles will provide details on how to build KIE Server extensions:

          Important note: While most of the work could be achieved already with 6.3.0.Final I'd strongly recommend to give it a go with 6.4.0 (and thus all dependencies refer to 6.4.0-SNAPSHOT) as the extensions have been simplified a lot.

          2015/09/11

          Unified KIE Execution Server - Part 3

          Part 3 of Unified KIE Execution Server deals with so called managed vs. unmanaged setup of the environment. In version 6.2 users went through Rules deployments perspective to create and manage KIE Execution Server instances.
          That approach required to have execution server configured and up and running. Some sort of online only registration that did not work if the kie server instance was down.

          In version 6.3, this has been enhanced to allow complete configuration of KIE Execution Servers inside workbench even if there is no actual instances configured. So let's first talk about managed and unmanaged instances....

          Managed KIE Execution Server 

          Managed instance is one that requires controller to be available to properly startup. Controller is a component responsible for keeping a configuration in centralized way. Though that does not mean there must be only single controller in the environment. Managed KIE Execution Servers are capable of dealing with multiple controllers.

          NOTE: It's important to mention that even though there can be multiple controllers they should be kept in sync to make sure that regardless which one of them is contacted by KIE Server instance it will provide same set of configuration.

          Controller is only needed when KIE Execution Server starts as this is the time when it needs to download the configuration before it can be properly started. In case KIE Execution Server is started it will keep trying to connect to controller until the connection is successfully established. That means that no containers will be deployed to it even when there is local storage available with configuration. The reason why it is like that is to ensure consistency. If KIE Execution Server was down and the configuration has changed, to make sure it will run with up to date configuration it must connect to controller to fetch that configuration.

          Configuration has been mentioned several times but what is that? Configuration is set of information:

          • containers to be deployed and started
          • configuration items - currently this is a place holder for further enhancements that will allow remotely configure KIE Execution Server components - timers, persistence, etc

          Controller is a component that is responsible for overall management of KIE Execution Servers. It provides a REST api that is divided into two parts:

          • controller itself that is exposed to interact with KIE Execution Server instances
          • administration that allows to remotely manage KIE Execution Server
            • add/remove servers
            • add/remove containers to/from the servers
            • start/stop containers on servers
          Controller deals only with KIE Execution Server configuration or definition to put it differently. It does not handle any runtime components of KIE Execution Server instances. They are always considered remote to controller. Controller is responsible for persisting the configuration to preserve restarts of the controller itself. It should manage the synchronization as well in case multiple controllers are configured to keep all definitions up to date on all instances of the controller.

          By default controller is shipped with KIE workbench (jbpm console) and allows fully featured management interface (both REST api and UI). It uses underlying git repository as persistent store and thus when GIT repositories are clustered (using Apache Zookeeper and Apache Helix) it will cover the controllers synchronization as well.

          Above diagram illustrates single controller (workbench) setup with multiple KIE Execution Server instances managed by it. Following diagram illustrates the clustered setup where there are multiple instances of controller sync over Zookeeper.


          In the above diagram we can see that KIE Execution Server instances are capable to connect to all controllers, but they will connect to only one. Each instance will attempt to connect to controller as long as it can reach one. Once connection is established with one of the controller it will skip other controllers.

          Working with managed servers

          There are two approaches that users can take when working with managed KIE Server instances:

          Configuration first
          With this approach, user will start working with controller (either UI or REST api) and create and configure KIE Execution Server definitions. That is composed of:
            • identification of the server (id and name + optionally version for improved readability)
            • containers 

          Register first
          Let the KIE Execution Server instance to auto register on controller and then configure it in terms of what containers to run on it. This is simply skipping the registration step done in first approach and populates it with server id, name and version directly upon auto registration (or to put it simple on connect)

          In general there is no big difference and which approach is taken is pretty much a personal preference. The outcome of both will be the same.

          Unmanaged KIE Execution Server

          Unmanaged KIE Execution server is in turn just a standalone instance and thus must be configured individually using REST/JMS api of the KIE Execution server itself. The configuration is persisted into a file that is considered internal server state. It's updated upon following operations:
          • deploy container
          • undeploy container
          • start container
          • stop container
          Note that KIE Execution server will start only the containers that are marked as started. Even if the KIE Execution Server will be restarted, upon boot it will only make containers available that were in started state before server was shutdown.


          In most of the case KIE Execution Server should be ran in managed mode as that provides lots of benefits in terms of control and configuration. More benefits will be noticed when discussing clustering and scalability of KIE Execution Servers where managed mode will show its true power :)

          Let's run in managed mode

          So that's about it in theory, let's try to run the KIE Execution Server in managed mode to see how this can be operated.

          For that we need to have one Wildfly instance that will host the controller - KIE Workbench and another one that will hold KIE Execution Server. Second we already have based on part 1 of the blog series.
          NOTE: You can run both KIE workbench and KIE Execution Server on the same application server instance but it won't show the improved manageability as they will always be up or down together. 

          So let's start with installing workbench on Wildfly. Similar to what we had to do for KIE Execution server we start with creating user(s):
          • kieserver (with password kieserver1!) that will be used to communicate between KIE Server and controller, that user must be member of following roles:
            • kie-server
            • rest-all
          • either add following roles to kieserver user or create another user that will be used to logon to KIE workbench to manage KIE Execution Servers
            • admin
            • rest-all
          To do so use the Wildfly utility script - add-user located in WILDFLY_HOME/bin and add application users. (for details how to do that part 1 of this blog series)

          Once we have the users created, let's deploy the application to it. Download KIE workbench for wildfly 8 and copy the way file into WILDFLY_HOME/standalone/deployments.

          NOTE: similar to KIE Server, personally I remove the version number and classifier from the war file name and make it as simple as 'kie-wb.war' that makes the context path short and thus easier to type.

          And now we are ready to launch KIE workbench, to do so go to WILDFLY_HOME/bin and start it with following command:

          ./standlone.sh --server-config=standalone-full.xml

          wait for the server to finish booting and then go to: 


          logon with user you created (e.g. kieserver) and go to Deployments --> Rules Deployments perspective. See following screencast (no audio) that showcase the capabilities described in this article. It starts with configure first approach and does show following:
          • create KIE Execution Server definition in the controller
            • specified identifier (first-kie-server) and name
          • create new container in the KIE Execution Server definition (org.jbpm:HR:1.0)
          • configure KIE Execution Server to be managed by specifying URL to the controller via system property:
            • -Dorg.kie.server.controller=http://localhost:8080/kie-wb/rest/controller
            • -Dorg.kie.server.id=first-kie-server (this is extremely important that this id matches one created in first step in the KIE Workbench)
          • start kie server and observe controller's log to see notification that kie server has connected to it
          • start container in controller and observe it being automatically started on KIE Execution Server instance
          • shutdown KIE Execution Server and observe logs and UI with updated status of kie server being disconnected
          • illustrates various manage options in controller and it effect on KIE Execution Server instance.


          So this screen cast concludes third part of the Unified KIE Execution Server series. With this in mind we move on into more advanced cases where we show integration with non java clients and clustering. More will come soon...