15.2. KIE Framework
15.2.1. KIE Systems
- Author
- Knowledge author using UI metaphors such as DRL, BPMN2, decision tables, and class models.
- Build
- Builds the authored knowledge into deployable units.
- For KIE this unit is a JAR.
- Test
- Test KIE knowledge before it is deployed to the application.
- Deploy
- Deploys the unit to a location where applications may use them.
- KIE uses Maven style repository.
- Utilize
- The loading of a JAR to provide a KIE session (KieSession), for which the application can interact with.
- KIE exposes the JAR at runtime via a KIE container (KieContainer).
- KieSessions, for the runtimes to interact with, are created from the KieContainer.
- Run
- System interaction with the KieSession, via API.
- Work
- User interaction with the KieSession, via command line or UI.
- Manage
- Manage any KieSession or KieContainer.
15.2.2. KieBase
KieHelper to load processes from various resources (for example, from the classpath or from the file system), and then create a new knowledge base from that helper. The following code snippet shows how to create a knowledge base consisting of only one process definition (using in this case a resource from the classpath):
KieHelper kHelper = new KieHelper();
KieBase kBase = kieHelper.addResource(ResourceFactory.newClassPathResource("MyProcess.bpmn")).build();KieHelper and ResourceFactory that are a part of Internal APIs org.kie.internal.io.ResourceFactory and org.kie.internal.utils.KieHelper. Using RuntimeManager is a recommended way to create knowledge base and knowledge session.
Note
org.kie.internal) are not supported as they are subject to change.
KieBase is a repository of all the application's knowledge definitions. It contains rules, processes, functions, and type models. The KieBase itself does not contain data; instead, sessions are created from the KieBase into which data can be inserted, and, ultimately, process instances may be started. Creating the KieBase can be quite heavy, whereas session creation is very light; therefore, it is recommended that KieBase be cached where possible to allow for repeated session creation. Accordingly, the caching mechanism is automatically provided by the KieContainer.
Table 15.1. kbase Attributes
| Attribute name | Default value | Admitted values | Meaning |
|---|---|---|---|
| name | none | any | The name which retrieves the KieBase from the KieContainer. This is the only mandatory attribute. |
| includes | none | any comma separated list | A comma separated list of other KieBases contained in this kmodule. The artifacts of all these KieBases will also be included in this one. |
| packages | all | any comma separated list | By default all the JBoss BRMS artifacts under the resources folder, at any level, are included into the KieBase. This attribute allows to limit the artifacts that will be compiled in this KieBase to only the ones belonging to the list of packages. |
| default | false | true, false | Defines if this KieBase is the default one for this module, so it can be created from the KieContainer without passing any name to it. There can be at most one default KieBase in each module. |
| equalsBehavior | identity | identity, equality | Defines the behavior of JBoss BRMS when a new fact is inserted into the Working Memory. With identity it always create a new FactHandle unless the same object isn't already present in the Working Memory, while with equality only if the newly inserted object is not equal (according to its equal method) to an already existing fact. |
| eventProcessingMode | cloud | cloud, stream | When compiled in cloud mode the KieBase treats events as normal facts, while in stream mode allow temporal reasoning on them. |
| declarativeAgenda | disabled | disabled, enabled | Defines if the Declarative Agenda is enabled or not. |
15.2.3. KieSession
KieSession ksession = kbase.newKieSession();
ProcessInstance processInstance = ksession.startProcess("com.sample.MyProcess");
import org.kie.api.runtime.process.ProcessRuntime;
KieSession stores and executes on runtime data. It is created from the KieBase, or, more easily, created directly from the KieContainer if it has been defined in the kmodule.xml file.
Note
org.kie.tx.lock.enabled and the environment entry TRANSACTION_LOCK_ENABLED to true. The default value of these properties is false.
Table 15.2. ksession Attributes
| Attribute name | Default value | Admitted values | Meaning |
|---|---|---|---|
| name | none | any | Unique name of this KieSession. Used to fetch the KieSession from the KieContainer. This is the only mandatory attribute. |
| type | stateful | stateful, stateless | A stateful session allows to iteratively work with the Working Memory, while a stateless one is a one-off execution of a Working Memory with a provided data set. |
| default | false | true, false | Defines if this KieSession is the default one for this module, so it can be created from the KieContainer without passing any name to it. In each module there can be at most one default KieSession for each type. |
| clockType | realtime | realtime, pseudo | Defines if events timestamps are determined by the system clock or by a psuedo clock controlled by the application. This clock is specially useful for unit testing temporal rules. |
| beliefSystem | simple | simple, jtms, defeasible | Defines the type of belief system used by the KieSession. |
15.2.3.1. The ProcessRuntime Interface
ProcessRuntime interface defines all the session methods for interacting with processes as shown below.
/**
* Start a new process instance. The process (definition) that should
* be used is referenced by the given process id.
*
* @param processId The id of the process that should be started
* @return the ProcessInstance that represents the instance of the process that was started
*/
ProcessInstance startProcess(String processId);
/**
* Start a new process instance. The process (definition) that should
* be used is referenced by the given process id. Parameters can be passed
* to the process instance (as name-value pairs), and these will be set
* as variables of the process instance.
*
* @param processId the id of the process that should be started
* @param parameters the process variables that should be set when starting the process instance
* @return the ProcessInstance that represents the instance of the process that was started
*/
ProcessInstance startProcess(String processId,
Map<String, Object> parameters);
/**
* Signals the engine that an event has occurred. The type parameter defines
* which type of event and the event parameter can contain additional information
* related to the event. All process instances that are listening to this type
* of (external) event will be notified. For performance reasons, this type of event
* signaling should only be used if one process instance should be able to notify
* other process instances. For internal event within one process instance, use the
* signalEvent method that also include the processInstanceId of the process instance
* in question.
*
* @param type the type of event
* @param event the data associated with this event
*/
void signalEvent(String type,
Object event);
/**
* Signals the process instance that an event has occurred. The type parameter defines
* which type of event and the event parameter can contain additional information
* related to the event. All node instances inside the given process instance that
* are listening to this type of (internal) event will be notified. Note that the event
* will only be processed inside the given process instance. All other process instances
* waiting for this type of event will not be notified.
*
* @param type the type of event
* @param event the data associated with this event
* @param processInstanceId the id of the process instance that should be signaled
*/
void signalEvent(String type,
Object event,
long processInstanceId);
/**
* Returns a collection of currently active process instances. Note that only process
* instances that are currently loaded and active inside the engine will be returned.
* When using persistence, it is likely not all running process instances will be loaded
* as their state will be stored persistently. It is recommended not to use this
* method to collect information about the state of your process instances but to use
* a history log for that purpose.
*
* @return a collection of process instances currently active in the session
*/
Collection<ProcessInstance> getProcessInstances();
/**
* Returns the process instance with the given id. Note that only active process instances
* will be returned. If a process instance has been completed already, this method will return
* null.
*
* @param id the id of the process instance
* @return the process instance with the given id or null if it cannot be found
*/
ProcessInstance getProcessInstance(long processInstanceId);
/**
* Aborts the process instance with the given id. If the process instance has been completed
* (or aborted), or the process instance cannot be found, this method will throw an
* IllegalArgumentException.
*
* @param id the id of the process instance
*/
void abortProcessInstance(long processInstanceId);
/**
* Returns the WorkItemManager related to this session. This can be used to
* register new WorkItemHandlers or to complete (or abort) WorkItems.
*
* @return the WorkItemManager related to this session
*/
WorkItemManager getWorkItemManager();15.2.3.2. Event Listeners
ProcessEventListener class to listen to process-related events, such as starting or completing a process and entering and leaving a node. An event object provides access to related information, like the process instance and node instance linked to the event. You can use this API to register your own event listeners. Here is a list of methods of the ProcessEventListener class:
public interface ProcessEventListener {
void beforeProcessStarted( ProcessStartedEvent event );
void afterProcessStarted( ProcessStartedEvent event );
void beforeProcessCompleted( ProcessCompletedEvent event );
void afterProcessCompleted( ProcessCompletedEvent event );
void beforeNodeTriggered( ProcessNodeTriggeredEvent event );
void afterNodeTriggered( ProcessNodeTriggeredEvent event );
void beforeNodeLeft( ProcessNodeLeftEvent event );
void afterNodeLeft( ProcessNodeLeftEvent event );
void beforeVariableChanged(ProcessVariableChangedEvent event);
void afterVariableChanged(ProcessVariableChangedEvent event);
}ProcessEventListener class:
import org.kie.api.event.process.ProcessEventListener;
15.2.3.3. Before and After Events
beforeNodeLeftEvent and the afterNodeLeftEvent of the node that is left (as the triggering of the second node is a direct result of leaving the first node). This enables you to derive cause relationships between events more easily. Similarly, all node triggered and node left events that are the direct result of starting a process, occur between the beforeProcessStarted and afterProcessStarted events. In general, if you just want to be notified when a particular event occurs, you must check for the before events only (as they occur immediately before the event actually occurs). If you are only looking at the after events, you may get an impression of events firing in the wrong order. As the after events are triggered as a stack, they only fire when all events that were triggered as a result of this event have already fired. Use the after events only if you want to ensure that all processing related to this has ended. For example, when you want to be notified when starting of a particular process instance has ended.
15.2.3.4. Correlation Keys
CorrelationKey that is composed of CorrelationProperties. CorrelationKey can have either a single property describing it or can be represented as multi valued properties set. The correlation feature, generally used for long running processes, requires you to enable persistence in order to permanently store correlation information.
CorrelationAwareProcessRuntime interface. This interface that exposes following methods:
/**
* Start a new process instance. The process (definition) that should
* be used is referenced by the given process id. Parameters can be passed
* to the process instance (as name-value pairs), and these will be set
* as variables of the process instance.
*
* @param processId the id of the process that should be started
* @param correlationKey custom correlation key that can be used to identify process instance
* @param parameters the process variables that should be set when starting the process instance
* @return the ProcessInstance that represents the instance of the process that was started
*/
ProcessInstance startProcess(String processId, CorrelationKey correlationKey, Map<String, Object> parameters);
/**
* Creates a new process instance (but does not yet start it). The process
* (definition) that should be used is referenced by the given process id.
* Parameters can be passed to the process instance (as name-value pairs),
* and these will be set as variables of the process instance. You should only
* use this method if you need a reference to the process instance before actually
* starting it. Otherwise, use startProcess.
*
* @param processId the id of the process that should be started
* @param correlationKey custom correlation key that can be used to identify process instance
* @param parameters the process variables that should be set when creating the process instance
* @return the ProcessInstance that represents the instance of the process that was created (but not yet started)
*/
ProcessInstance createProcessInstance(String processId, CorrelationKey correlationKey, Map<String, Object> parameters);
/**
* Returns the process instance with the given correlationKey. Note that only active process instances
* will be returned. If a process instance has been completed already, this method will return
* null.
*
* @param correlationKey the custom correlation key assigned when process instance was created
* @return the process instance with the given id or null if it cannot be found
*/
ProcessInstance getProcessInstance(CorrelationKey correlationKey);
CorrelationAwareProcessRuntime:
import org.kie.internal.process.CorrelationAwareProcessRuntime;
15.2.3.5. Threads
Thread.sleep(...) as part of a script does not make the engine continue execution elsewhere, but blocks the engine thread during that period. The same principle applies to service tasks. When a service task is reached in a process, the engine invokes the handler of this service synchronously. The engine waits for the completeWorkItem(...) method to return before continuing execution. It is important that your service handler executes your service asynchronously if its execution is not instantaneous. An example of this is a service task that invokes an external service. Since the delay in invoking this service remotely and waiting for the results may take too long, invoking this service asynchronously is advised. This means that the handler only invokes the service and notifies the engine later when the results are available. In the mean time, the process engine then continues execution of the process.
15.2.4. KieFileSystem
KieBases and KieSessions belonging to a KieModule programmatically instead of the declarative definition in the kmodule.xml file. The same programmatic API also allows in explicitly adding the file containing the Kie artifacts instead of automatically read them from the resources folder of your project. To do that it is necessary to create a KieFileSystem, a sort of virtual file system, and add all the resources contained in your project to it.
KieFileSystem from the KieServices. The kmodule.xml configuration file must be added to the filesystem. This is a mandatory step. Kie also provides a convenient fluent API, implemented by the KieModuleModel, to programmatically create this file.
KieModuleModel from the KieServices, configure it with the desired KieBases and KieSessions, convert it in XML and add the XML to the KieFileSystem. This process is shown by the following example:
Example 15.1. Creating a kmodule.xml programmatically and adding it to a KieFileSystem
import org.kie.api.KieServices;
import org.kie.api.builder.model.KieModuleModel;
import org.kie.api.builder.model.KieBaseModel;
import org.kie.api.builder.model.KieSessionModel;
import org.kie.api.builder.KieFileSystem;
//...
KieServices kieServices = KieServices.Factory.get();
KieModuleModel kieModuleModel = kieServices.newKieModuleModel();
KieBaseModel kieBaseModel1 = kieModuleModel.newKieBaseModel( "KBase1 ")
.setDefault( true )
.setEqualsBehavior( EqualityBehaviorOption.EQUALITY )
.setEventProcessingMode( EventProcessingOption.STREAM );
KieSessionModel ksessionModel1 = kieBaseModel1.newKieSessionModel( "KSession1" )
.setDefault( true )
.setType( KieSessionModel.KieSessionType.STATEFUL )
.setClockType( ClockTypeOption.get("realtime") );
KieFileSystem kfs = kieServices.newKieFileSystem();KieFileSystem, through its fluent API, all others Kie artifacts composing your project. These artifacts have to be added in the same position of a corresponding usual Maven project.
15.2.5. KieResources
Example 15.2. Adding Kie artifacts to a KieFileSystem
import org.kie.api.builder.KieFileSystem;
KieFileSystem kfs = ...
kfs.write( "src/main/resources/KBase1/ruleSet1.drl", stringContainingAValidDRL )
.write( "src/main/resources/dtable.xls",
kieServices.getResources().newInputStreamResource( dtableFileStream ) );Resources. In the latter case the Resources can be created by the KieResources factory, also provided by the KieServices. The KieResources provides many convenient factory methods to convert an InputStream, a URL, a File, or a String representing a path of your file system to a Resource that can be managed by the KieFileSystem.
Resource can be inferred from the extension of the name used to add it to the KieFileSystem. However it also possible to not follow the Kie conventions about file extensions and explicitly assign a specific ResourceType to a Resource as shown below:
Example 15.3. Creating and adding a Resource with an explicit type
import org.kie.api.builder.KieFileSystem;
KieFileSystem kfs = ...
kfs.write( "src/main/resources/myDrl.txt",
kieServices.getResources().newInputStreamResource( drlStream )
.setResourceType(ResourceType.DRL) );KieFileSystem and build it by passing the KieFileSystem to a KieBuilder
KieFileSystem are successfully built, the resulting KieModule is automatically added to the KieRepository. The KieRepository is a singleton acting as a repository for all the available KieModules.

Where did the comment section go?
Red Hat's documentation publication system recently went through an upgrade to enable speedier, more mobile-friendly content. We decided to re-evaluate our commenting platform to ensure that it meets your expectations and serves as an optimal feedback mechanism. During this redesign, we invite your input on providing feedback on Red Hat documentation via the discussion platform.