JBoss.org Community Documentation

- Prev
- Next

## Chapter 4. KIE

## 4.1. Overview

### 4.1.1. Anatomy of Projects

The process of researching an integration knowledge solution for Drools and jBPM has simply used the "droolsjbpm" group name. This name permeates github accounts and maven poms. As scopes broadened and new projects were spun KIE, an acronym for Knowledge Is Everything, was chosen as the new group name. The KIE name is also used for the shared aspects of the system; such as the unified build, deploy and utilization.

KIE currently consists of the following sub projects:

Figure 4.1. KIE Anatomy

OptaPlanner, a local search and optimization tool, has been spun off from Drools Planner and is now a top level project with Drools and jBPM. This was a natural evolution as Optaplanner, while having strong Drools integration, has long been independant of Drools.

From the Polymita acquisition, along with other things, comes the powerful Dashboard Builder which provides powerful reporting capabities. Dashboard Builder is currently a temporary name and after the 6.0 release a new name will be chosen. Dashboard Builder is completely independant of Drools and jBPM and will be used by many projects at JBoss, and hopefully outside of JBoss :)

UberFire is the new base workbench project, spun off from the ground up rewrite. UberFire provides Eclipse-like workbench capabilities, with panels and perspectives from plugins. The project is independant of Drools and jBPM and anyone can use it as a basis of building flexible and powerful workbenches. UbeFire will be used for console and workbench development throughout JBoss.

It was determined that the Guvnor brand leaked too much from it's intended role; such as the authoring metaphores, like Decision Tables, being considered Guvnor components instead of Drools components. This wasn't helped by the monolithic projects structure used in 5.x for Guvnor. In 6.0 Guvnor 's focus has been narrowed to encapsulates the set of UberFire plugins that provide the basis for building a web based IDE. Such as Maven integration for building and deploying, management of Maven repositories and activity notifications via inboxes. Drools and jBPM build workbench distributions using Uberfire as the base and including a set of plugins, such as Guvnor, along with their own plugins for things like decision tables, guided editors, bpm2 designer, human tasks. The Drools workbench is called Drools-WB. KIE-WB is the uber workbench that combined all the Guvnor, Drools and jBPM plugins. The jBPM-WB is ghosted out, as it doesn't actually exist, being made redundant by KIE-WB.

### 4.1.2. Lifecycles

The different aspects, or life cycles, of working with KIE system, whether it's Drools or jBPM, can typically be broken down into the following:

- Author

  - Authoring of knowledge using a UI metaphor, such as: drl, BPMN2, decision table, class models.

- Build

  - Builds the authored knowledge into deployable units.

  - For KIE this unit is a jar.

- Test

  - Test KIE knowedge before it's deployed to the application.

- Deploy

  - Deploys the unit to a location where applications may utilize (consume) 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 runtime's 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.

## 4.2. Build, Deploy, Utilize and Run

### 4.2.1. Introduction

6.0 introduces a new configuration and convention approach to building knowledge bases, instead of the using the programmatic builder approach in 5.x. Atlhough a builder is still available to fall back on, as it's used for the tooling integration.

Building now uses Maven, and aligns with Maven practices. A KIE projcet or module is simply a Maven java project or module; with an additional meta data file META-INF/kmodule.xml. The kmodule.xml file is the descriptor that selects resources to knowledge bases and configures those knowledge bases and sessions. There is also alternative xml support via Spring and OSGi BluePrints.

While standard Maven can build and package KIE resources, it will not provide validation at build time. There is a Maven plugin which is recommend to use to get build time validation. The plugin also pre-genenerates many classes, making the runtime loading faster too.

The example project layout and maven pom descriptor is illustarted in the screenshot

Figure 4.2. Example project layout and maven pom

KIE uses defaults to minimise the amount of configuration. With an empty kmodule.xml being the simplest configuration. There must always be a kmodule.xml file, even if empty, as it's used for discover of the jar and it's contents.

Maven can either 'mvn install' to deploy a KieModule to the local machine, where all other applications on the local machine use it. Or it can 'mvn 'deploy' to push the KieModule to a remote Maven repository. Building the Application wil pull in the KieModule, popualting it's local Maven repository, as it does so.

Figure 4.3. Example project layout and maven pom

Jars can be deployed in one of two ways. Either added to the classpath, like any other jar in a Maven dependency listing, or they can be dynamically loaded at runtime. KIE will scan the classpath to find all the jars with a kmodule.xml in it. Each found jar is represented by the KieModule interface. The term Classpath KieModules and dynamic KieModule is used to refer to the two loading approaches. While dynamic modules supports side by side versioning, classpath modules do not. Further once module is on the classpath, no other version may be loaded dynamically.

Detailed referencs for the api are included in the next sections, the impatiant can jump straight to the examples section, which is fairly intuitive for the different use cases.

### 4.2.2. Building

Figure 4.4. org.kie.api.core.builder

#### 4.2.2.1. Creating and building a Kie Project

A Kie Project has the structure of a normal maven project with the only peculiarity of including a kmodule.xml file defining in a declaratively way the `KieBase`s and `KieSession`s that can be created from it. This file has to be placed in the resources/META-INF folder of the maven project while all the other Kie artifacts, such as DRL or a Excel files, must be stored in the resources folder or in any other subfolder under it.

Since meaningful defaults have been provided for all configuration aspects, the simplest kmodule.xml file can contain just an empty kmodule tag like the following:

Example 4.1. An empty kmodule.xml file

    <?xml version="1.0" encoding="UTF-8"?>

    <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"/>

In this way the kmodule will contain one single default `KieBase`. All Kie assets stored under the resources folder, or any of its subfolders, will be compiled and added to it. To trigger the building of these artifacts it is enough to create a `KieContainer` for them.

Figure 4.5. KieContainer

For this simple case it is enough to create a `KieContainer` that reads the files to be built from the classpath:

Example 4.2. Creating a KieContainer from the classpath

    KieServices kieServices = KieServices.Factory.get();

    KieContainer kContainer = kieServices.getKieClasspathContainer();

`KieServices` is the interface from where it possible to access all the Kie building and runtime facilities:

Figure 4.6. KieServices

In this way all the java sources and the Kie resources are compiled and deployed into the KieContainer which makes its contents available for use at runtime.

#### 4.2.2.2. The kmodule.xml file

As anticipated in the former section the kmodule.xml file is the place where it is possible to declaratively configure the `KieBase`(s) and `KieSession`(s) that can be created from a KIE project.

In particular a `KieBase` is a repository of all the application's knowledge definitions. It will contain 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 from which process instances may be started. Creating the `KieBase` can be heavy, whereas session creation is very light, so it is recommended that `KieBase` be cached where possible to allow for repeated session creation. However end-users usually shouldn't worry about it, because this caching mechanism is already automatically provided by the `KieContainer`.

Figure 4.7. KieBase

Conversely the `KieSession` stores and executes on the runtime data. It is created from the `KieBase` or more easily can be created directly from the `KieContainer` if it has been defined in the kmodule.xml file

Figure 4.8. KieSession

The kmodule.xml allows to define and configure one or more `KieBase`s and for each `KieBase` all the different `KieSession`s that can be created from it, as showed by the follwing example:

Example 4.3. A sample kmodule.xml file

    <kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

            xmlns="http://jboss.org/kie/6.0.0/kmodule">

      <kbase name="KBase1" default="true" eventProcessingMode="cloud" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg1">

        <ksession name="KSession2_1" type="stateful" default="true/">

        <ksession name="KSession2_1" type="stateless" default="false/" beliefSystem="jtms">

      </kbase>

      <kbase name="KBase2" default="false" eventProcessingMode="stream" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg2, org.domain.pkg3" includes="KBase1">

        <ksession name="KSession2_1" type="stateful" default="false" clockType="realtime">

          <fileLogger file="drools.log" threaded="true" interval="10"/>

          <workItemHandlers>

            <workItemHandler name="name" type="org.domain.WorkItemHandler"/>

          </workItemHandlers>

          <listeners>

            <ruleRuntimeEventListener type="org.domain.RuleRuntimeListener"/>

            <agendaEventListener type="org.domain.FirstAgendaListener"/>

            <agendaEventListener type="org.domain.SecondAgendaListener"/>

            <processEventListener type="org.domain.ProcessListener"/>

          </listeners>

        </ksession>

      </kbase>

    </kmodule>

Here 2 `KieBase`s have been defined and it is possible to instance 2 different types of `KieSession`s from the first one, while only one from the second. A list of the attributes that can be defined on the kbase tag, together with their meaning and default values follows:

Table 4.1. kbase Attributes

Attribute name | Default value | Admitted values | Meaning
--- | --- | --- | ---
name | none | any | The name with which retrieve this 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 be also included in this one.
packages | all | any comma separated list | By default all the Drools 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 Drools 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.

In the same way also all attributes of the ksession tag (except of course the name) have meaningful default. They are listed and described in the following table:

Table 4.2. ksession Attributes

Attribute name | Default value | Admitted values | Meaning
--- | --- | --- | ---
name | none | any | The name with which retrieve this 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.

As outlined in the former kmodule.xml sample, it is also possible to declaratively create on each `KieSession` a file (or a console) logger, one or more `WorkItemHandler`s and some listeners that can be of 3 different types: ruleRuntimeEventListener, agendaEventListener and processEventListener

Having defined a kmodule.xml like the one in the former sample, it is now possible to simply retrieve the KieBases and KieSessions from the KieContainer using their names.

Example 4.4. Retriving KieBases and KieSessions from the KieContainer

    KieServices kieServices = KieServices.Factory.get();

    KieContainer kContainer = kieServices.getKieClasspathContainer();

    KieBase kBase1 = kContainer.getKieBase("KBase1");

    KieSession kieSession1 = kContainer.newKieSession("KSession2_1");

    StatelessKieSession kieSession2 = kContainer.newStatelessKieSession("KSession2_2");

It has to be noted that since KSession2_1 and KSession2_2 are of 2 different types (the first is stateful, while the second is stateless) it is necessary to invoke 2 different methods on the `KieContainer` according to their declared type. If the type of the `KieSession` requested to the `KieContainer` doesn't correspond with the one declared in the kmodule.xml file the `KieContainer` will throw a `RuntimeException`. Also since a `KieBase` and a `KieSession` have been flagged as default is it possible to get them from the `KieContainer` without passing any name.

Example 4.5. Retriving default KieBases and KieSessions from the KieContainer

    KieContainer kContainer = ...

    KieBase kBase1 = kContainer.getKieBase(); // returns KBase1

    KieSession kieSession1 = kContainer.newKieSession(); // returns KSession2_1

Since a Kie project is also a maven project the groupId, artifactId and version declared in the pom.xml file are also used to generate a `ReleaseId` that uniquely identify this project inside your application. This also allows to create a new KieContainer from that project by simply passing its `ReleaseId` to the `KieServices`.

Example 4.6. Creating a KieContainer of an existing project retriving it by ReleaseId

    KieServices kieServices = KieServices.Factory.get();

    ReleaseId releaseId = kieServices.newReleaseId( "org.acme", "myartifact", "1.0" );

    KieContainer kieContainer = kieServices.newKieContainer( releaseId );

#### 4.2.2.3. Building with Maven

The KIE plugin for maven ensures that artefact resources are validated and pre-compiled, it is recommended that this is used at all times. To use the plugin simple add it to the build section of the Maven pom.xml

Example 4.7. Adding the KIE plugin to a Maven pom.xml

      <build>

        <plugins>

          <plugin>

            <groupId>org.kie</groupId>

            <artifactId>kie-maven-plugin</artifactId>

            <version>${project.version}</version>

            <extensions>true</extensions>

          </plugin>

        </plugins>

      </build>

Building a KIE module without the Maven plugin will copy all the resources, as is, into the resulting JAR. When that JAR is loaded by the runtime, it will attempt to build all the resources then. If there are compilation issues it will return a null KieContainer. It also pushes the compilation overhead to the runtime. In general this is not recommended, and the Maven plugin should always be used.

#### 4.2.2.4. Defining a KieModule programmatically

It is also possible to define the `KieBase`s and `KieSession`s belonging to a KieModule programatically instead of declaratively define them in the kmodule.xml file. The same programatic API also allows to explicitly add 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.

Figure 4.9. KieFileSystem

Like all other Kie core component you can obtain an instance of the `KieFileSystem` from the `KieServices`. One of the thing that for sure it will be necessary to add to this file system is the kmodule.xml configuration file. As anticipated above Kie also provides a convenient fluent API, implemented by the `KieModuleModel`, to programatically create this file.

Figure 4.10. KieModuleModel

To do this in practice it is necessary to create a `KieModuleModel` from the `KieServices`, configure it with the desired `KieBase`s and `KieSession`s, convert it in xml and add the xml to the `KieFileSystem`. This process is shown by the following example:

Example 4.8. Creating a kmodule.xml programmatically and adding it to a 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();

At this point it is also necessary to add to the `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.

Example 4.9. Adding Kie artifacts to a KieFileSystem

    KieFileSystem kfs = ...

    kfs.write( "src/main/resources/KBase1/ruleSet1.drl", stringContainingAValidDRL )

            .write( "src/main/resources/dtable.xls",

                    kieServices.getResources().newInputStreamResource( dtableFileStream ) );

This example shows that it is possible to add the Kie artifacts both as plain Strings and as `Resource`s. In this second case the `Resource`s 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`.

Figure 4.11. KieResources

Normally the type of a `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 extension and then explicitly assign a specific `ResourceType` to a`Resource` as in the following example

Example 4.10. Creating and adding a Resource with an explicit type

    KieFileSystem kfs = ...

    kfs.write( "src/main/resources/myDrl.txt",

               kieServices.getResources().newInputStreamResource( drlStream )

                          .setResourceType(ResourceType.DRL) );

After having added to the `KieFileSystem` all the resources that has to be included into the project, it is possible to build it by passing the `KieFileSystem` to a `KieBuilder`

Figure 4.12. KieBuilder

When a the contents of a `KieFileSystem` is successfully built, the `KieModule` resulting from this compilation is automatically added to the `KieRepository`. The `KieRepository` is a singleton acting as a repository for all the available `KieModule`s.

Figure 4.13. KieRepository

After this it is possible to create through the `KieServices` a new `KieContainer` for that `KieModule` using its `ReleaseId`. However, since in this case the `KieFileSystem` don't contain any pom.xml file (it is possible to add one using the `KieFileSystem.writePomXML` method), Kie cannot determine the `ReleaseId` of the `KieModule` and assign to it a default one. This default `ReleaseId` can be obtained from the `KieRepository` and used to identify the `KieModule` inside the `KieRepository` itself. The following example shows this whole process.

Example 4.11. Building the contents of a KieFileSystem and creating a KieContainer

    KieServices kieServices = KieServices.Factory.get();

    KieFileSystem kfs = ...

    kieServices.newKieBuilder( kfs ).buildAll();

    KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());

At this point it is possible to get `KieBase`s and create new `KieSession`s from this `KieContainer` exactly in the same way as in the case of a `KieContainer` created directly from the classpath.

It is a best practice to check the compilation results. The `KieBuilder` can report compilation results of 3 different severities: ERROR, WARNING and INFO. An ERROR indicates that the compilation of the project failed and in the case no `KieModule` is produced and then nothing is added to the `KieRepository`. WARNING and INFO results can be ignored, but are available for inspection nonetheless.

Example 4.12. Checking that a compilation didn't produce any error

    KieBuilder kieBuilder = kieServices.newKieBuilder( kfs ).buildAll();

    assertEquals( 0, kieBuilder.getResults().getMessages( Message.Level.ERROR ).size() );

#### 4.2.2.5. Changing the Default Build Result Severity

In some cases, it is possible to change the default severity of a type of build result. For instance, when a new rule with the same name of an existing rule is added to a package, the default behavior is to replace the old rule by the new rule and report it as an INFO. This is probably ideal for most use cases, but in some deployments the user might want to prevent the rule update and report it as an error.

Changing the default severity for a result type is configured like any other option in Drools and can be done by API calls, system properties or configuration files. As of this version, Drools supports configurable result severity for rule updates and function updates. To configure it using system properties or configuration files, the user has to use the following properties:

Example 4.13. Setting the severity using properties

    // sets the severity of rule updates
    drools.kbuilder.severity.duplicateRule = <INFO|WARNING|ERROR>
    // sets the severity of function updates
    drools.kbuilder.severity.duplicateFunction = <INFO|WARNING|ERROR>

### 4.2.3. Deploying

#### 4.2.3.1. KieBase

The `KieBase` is a repository of all the application's knowledge definitions. It will contain 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 from which process instances may be started. The `KieBase` can be obtained from the `KieContainer` containing the `KieModule` where the `KieBase` has been defined.

Figure 4.14. KieBase

Sometimes, for instance in a OSGi environment, the `KieBase` needs to resolve types that are not in the default class loader. In this case it will be necessary to create a `KieBaseConfiguration` with an additional class loader and pass it to `KieContainer` when creating a new `KieBase` from it.

Example 4.14. Creating a new KieBase with a custom ClassLoader

    KieServices kieServices = KieServices.Factory.get();

    KieBaseConfiguration kbaseConf = kieServices.newKieBaseConfiguration( null, MyType.class.getClassLoader() );

    KieBase kbase = kieContainer.newKieBase( kbaseConf );

#### 4.2.3.2. KieSessions and KieBase Modifications

KieSessions will be discussed in more detail in section "Running". The `KieBase` creates and returns `KieSession` objects, and it may optionally keep references to those. When `KieBase` modifications occur those modifications are applied against the data in the sessions. This reference is a weak reference and it is also optional, which is controlled by a boolean flag.

#### 4.2.3.3. KieScanner

The `KieScanner` allows to continously monitoring your maven repository to check if a new release of a Kie project has been installed and if so deploying it in the `KieContainer` wrapping that project. The use of the `KieScanner` requires kie-ci.jar to be on the classpath.

Figure 4.15. KieScanner

In more detail a `KieScanner` can be registered on a `KieContainer` as in the following example.

Example 4.15. Registering and starting a KieScanner on a KieContainer

    KieServices kieServices = KieServices.Factory.get();

    ReleaseId releaseId = kieServices.newReleaseId( "org.acme", "myartifact", "1.0-SNAPSHOT" );

    KieContainer kContainer = kieServices.newKieContainer( releaseId );

    KieScanner kScanner = kieServices.newKieScanner( kContainer );

    // Start the KieScanner polling the maven repository every 10 seconds

    kScanner.start( 10000L );

In this example the `KieScanner` is configured to run with a fixed time interval, but it is also possible to run it on demand by invoking the `scanNow()` method on it. If the `KieScanner` finds in the maven repository an updated version of the Kie project used by that `KieContainer` it automatically downloads the new version and triggers an incremental build of the new project. From this moment all the new `KieBase`s and `KieSession`s created from that `KieContainer` will use the new project version.

### 4.2.4. Running

#### 4.2.4.1. KieBase

The `KieBase` is a repository of all the application's knowledge definitions. It will contain 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 from which process instances may be started. The `KieBase` can be obtained from the `KieContainer` containing the `KieModule` where the `KieBase` has been defined.

Example 4.16. Getting a KieBase from a KieContainer

    KieBase kBase = kContainer.getKieBase();

#### 4.2.4.2. KieSession

The `KieSession` stores and executes on the runtime data. It is created from the `KieBase`.

Figure 4.16. KieSession

Example 4.17. Create a KieSession from a KieBase

    KieSession ksession = kbase.newKieSession();

#### 4.2.4.3. KieRuntime

##### 4.2.4.3.1. KieRuntime

The `KieRuntime` provides further methods that are applicable to both rules and processes, such as setting globals and registering channels. ("Exit point" is an obsolete synonym for "channel".)

Figure 4.17. KieRuntime

###### 4.2.4.3.1.1. Globals

Globals are named objects that are made visible to the rule engine, but in a way that is fundamentally different from the one for facts: changes in the object backing a global do not trigger reevaluation of rules. Still, globals are useful for providing static information, as an object offering services that are used in the RHS of a rule, or as a means to return objects from the rule engine. When you use a global on the LHS of a rule, make sure it is immutable, or, at least, don't expect changes to have any effect on the behavior of your rules.

A global must be declared in a rules file, and then it needs to be backed up with a Java object.

    global java.util.List list

With the Knowledge Base now aware of the global identifier and its type, it is now possible to call `ksession.setGlobal()` with the global's name and an object, for any session, to associate the object with the global. Failure to declare the global type and identifier in DRL code will result in an exception being thrown from this call.

    List list = new ArrayList();

    ksession.setGlobal("list", list);

Make sure to set any global before it is used in the evaluation of a rule. Failure to do so results in a `NullPointerException`.

#### 4.2.4.4. Event Model

The event package provides means to be notified of rule engine events, including rules firing, objects being asserted, etc. This allows you, for instance, to separate logging and auditing activities from the main part of your application (and the rules).

The `KieRuntimeEventManager` interface is implemented by the `KieRuntime` which provides two interfaces, `RuleRuntimeEventManager` and `ProcessEventManager`. We will only cover the `RuleRuntimeEventManager` here.

Figure 4.18. KieRuntimeEventManager

The `RuleRuntimeEventManager` allows for listeners to be added and removed, so that events for the working memory and the agenda can be listened to.

Figure 4.19. RuleRuntimeEventManager

The following code snippet shows how a simple agenda listener is declared and attached to a session. It will print matches after they have fired.

Example 4.18. Adding an AgendaEventListener

    ksession.addEventListener( new DefaultAgendaEventListener() {

        public void afterMatchFired(AfterMatchFiredEvent event) {

            super.afterMatchFired( event );

            System.out.println( event );

        }

    });

Drools also provides `DebugRuleRuntimeEventListener` and `DebugAgendaEventListener` which implement each method with a debug print statement. To print all Working Memory events, you add a listener like this:

Example 4.19. Adding a DebugRuleRuntimeEventListener

    ksession.addEventListener( new DebugRuleRuntimeEventListener() );

All emitted events implement the `KieRuntimeEvent` interface which can be used to retrieve the actual `KnowlegeRuntime` the event originated from.

Figure 4.20. KieRuntimeEvent

The events currently supported are:

- MatchCreatedEvent

- MatchCancelledEvent

- BeforeMatchFiredEvent

- AfterMatchFiredEvent

- AgendaGroupPushedEvent

- AgendaGroupPoppedEvent

- ObjectInsertEvent

- ObjectDeletedEvent

- ObjectUpdatedEvent

- ProcessCompletedEvent

- ProcessNodeLeftEvent

- ProcessNodeTriggeredEvent

- ProcessStartEvent

#### 4.2.4.5. KieRuntimeLogger

The KieRuntimeLogger uses the comprehensive event system in Drools to create an audit log that can be used to log the execution of an application for later inspection, using tools such as the Eclipse audit viewer.

Figure 4.21. KieLoggers

Example 4.20. FileLogger

    KieRuntimeLogger logger =

      KieServices.Factory.get().newFileLogger(ksession, "logdir/mylogfile");

    ...

    logger.close();

#### 4.2.4.6. Commands and the CommandExecutor

KIE has the concept of stateful or stateless sessions. Stateful sessions have already been covered, which use the standard KieRuntime, and can be worked with iteratively over time. Stateless is a one-off execution of a KieRuntime with a provided data set. It may return some results, with the session being disposed at the end, prohibiting further iterative interactions. You can think of stateless as treating an engine like a function call with optional return results.

The foundation for this is the `CommandExecutor` interface, which both the stateful and stateless interfaces extend. This returns an `ExecutionResults`:

Figure 4.22. CommandExecutor

Figure 4.23. ExecutionResults

The `CommandExecutor` allows for commands to be executed on those sessions, the only difference being that the StatelessKieSession executes `fireAllRules()` at the end before disposing the session. The commands can be created using the `CommandExecutor` .The Javadocs provides the full list of the provided comands using the `CommandExecutor` .

SetGloban and getGlobal are two commands relevant to both Drools and jBPM.

Set Global calls setGlobal underneath. The optional boolean indicates on whether the command should return value as part of the `ExecutionResults`. If true it uses the same name as the global name. A String cna be used instead of the boolean, if an alternative name is desired.

Example 4.21. Set Global Command

    <!-- <br/> --><span class="java_type">StatelessKieSession</span><!-- <br/> --><span class="java_plain">&nbsp;ksession&nbsp;</span><!-- <br/> --><span class="java_operator">=</span><!-- <br/> --><span class="java_plain">&nbsp;kbase</span><!-- <br/> --><span class="java_separator">.</span><!-- <br/> --><span class="java_plain">newStatelessKieSession</span><!-- <br/> --><span class="java_separator">();</span>
    <!--  --><br/><span class="java_type">ExecutionResults</span><span class="java_plain">&nbsp;bresults&nbsp;</span><span class="java_operator">=</span>
    <!--  --><br/><span class="java_plain">&nbsp;&nbsp;&nbsp;&nbsp;ksession</span><span class="java_separator">.</span><span class="java_plain">execute</span><span class="java_separator">(</span><span class="java_plain">&nbsp;</span><span class="java_type">CommandFactory</span><span class="java_separator">.</span><span class="java_plain">newSetGlobal</span><span class="java_separator">(</span><span class="java_plain">&nbsp;</span><span class="java_literal">&quot;stilton&quot;</span><span class="java_separator">,</span><span class="java_plain">&nbsp;</span><span class="java_keyword">new</span><span class="java_plain">&nbsp;</span><span class="java_type">Cheese</span><span class="java_separator">(</span><span class="java_plain">&nbsp;</span><span class="java_literal">&quot;stilton&quot;</span><span class="java_plain">&nbsp;</span><span class="java_separator">),</span><span class="java_plain">&nbsp;</span><span class="java_literal">true</span><span class="java_separator">);</span>
    <!--  --><br/><span class="java_type">Cheese</span><span class="java_plain">&nbsp;stilton&nbsp;</span><span class="java_operator">=</span><span class="java_plain">&nbsp;bresults</span><span class="java_separator">.</span><span class="java_plain">getValue</span><span class="java_separator">(</span><span class="java_plain">&nbsp;</span><span class="java_literal">&quot;stilton&quot;</span><span class="java_plain">&nbsp;</span><span class="java_separator">);</span>

Allows an existing global to be returned. The second optional String argument allows for an alternative return name.

Example 4.22. Get Global Command

    StatelessKieSession ksession = kbase.newStatelessKieSession();

    ExecutionResults bresults =

        ksession.execute( CommandFactory.getGlobal( "stilton" );

    Cheese stilton = bresults.getValue( "stilton" );

The examples above all execute single commands. The `BatchExecution` represents a composite command, created from a list of commands. It will iterate over the list and execute each command in turn. This means you can insert some objects, start a process, call fireAllRules and execute a query, all in a single `execute(...)` call, which is quite powerful.

The StatelessKieSession will execute `fireAllRules()` automatically at the end. However the keen-eyed reader probably has already noticed the `FireAllRules` command and wondered how that works with a StatelessKieSession. The `FireAllRules` command is allowed, and using it will disable the automatic execution at the end; think of using it as a sort of manual override function.

Any command, in the batch, that has an out identifier set will add its results to the returned `ExecutionResults` instance. Let's look at a simple example to see how this works. The example presented includes command from the Drools and jBPM, for the sake of illustartion. They are covered in more detail in the Drool and jBPM specific sections.

Example 4.23. BatchExecution Command

    StatelessKieSession ksession = kbase.newStatelessKieSession();

    List cmds = new ArrayList();

    cmds.add( CommandFactory.newInsertObject( new Cheese( "stilton", 1), "stilton") );

    cmds.add( CommandFactory.newStartProcess( "process cheeses" ) );

    cmds.add( CommandFactory.newQuery( "cheeses" ) );

    ExecutionResults bresults = ksession.execute( CommandFactory.newBatchExecution( cmds ) );

    Cheese stilton = ( Cheese ) bresults.getValue( "stilton" );

    QueryResults qresults = ( QueryResults ) bresults.getValue( "cheeses" );

In the above example multiple commands are executed, two of which populate the `ExecutionResults`. The query command defaults to use the same identifier as the query name, but it can also be mapped to a different identifier.

All commands support XML and jSON marshalling using XStream, as well as JAXB marshalling. This is covered in section XXX.

#### 4.2.4.7. StatelessKieSession

The `StatelessKieSession` wraps the `KieSession`, instead of extending it. Its main focus is on decision service type scenarios. It avoids the need to call `dispose()`. Stateless sessions do not support iterative insertions and the method call `fireAllRules()` from Java code; the act of calling `execute()` is a single-shot method that will internally instantiate a `KieSession`, add all the user data and execute user commands, call `fireAllRules()`, and then call `dispose()`. While the main way to work with this class is via the `BatchExecution` (a subinterface of `Command`) as supported by the `CommandExecutor` interface, two convenience methods are provided for when simple object insertion is all that's required. The `CommandExecutor` and `BatchExecution` are talked about in detail in their own section.

Figure 4.24. StatelessKieSession

Our simple example shows a stateless session executing a given collection of Java objects using the convenience API. It will iterate the collection, inserting each element in turn.

Example 4.24. Simple StatelessKieSession execution with a Collection

    StatelessKieSession ksession = kbase.newStatelessKieSession();

    ksession.execute( collection );

If this was done as a single Command it would be as follows:

Example 4.25. Simple StatelessKieSession execution with InsertElements Command

    ksession.execute( CommandFactory.newInsertElements( collection ) );

If you wanted to insert the collection itself, and the collection's individual elements, then `CommandFactory.newInsert(collection)` would do the job.

Methods of the `CommandFactory` create the supported commands, all of which can be marshalled using XStream and the `BatchExecutionHelper`. `BatchExecutionHelper` provides details on the XML format as well as how to use Drools Pipeline to automate the marshalling of `BatchExecution` and `ExecutionResults`.

`StatelessKieSession` supports globals, scoped in a number of ways. I'll cover the non-command way first, as commands are scoped to a specific execution call. Globals can be resolved in three ways.

- The StatelessKieSession method `getGlobals()` returns a Globals instance which provides access to the session's globals. These are shared for all execution calls. Exercise caution regarding mutable globals because execution calls can be executing simultaneously in different threads.

  Example 4.26. Session scoped global

      StatelessKieSession ksession = kbase.newStatelessKieSession();

      // Set a global hbnSession, that can be used for DB interactions in the rules.

      ksession.setGlobal( "hbnSession", hibernateSession );

      // Execute while being able to resolve the "hbnSession" identifier.

      ksession.execute( collection );

- Using a delegate is another way of global resolution. Assigning a value to a global (with `setGlobal(String, Object)`) results in the value being stored in an internal collection mapping identifiers to values. Identifiers in this internal collection will have priority over any supplied delegate. Only if an identifier cannot be found in this internal collection, the delegate global (if any) will be used.

- The third way of resolving globals is to have execution scoped globals. Here, a `Command` to set a global is passed to the `CommandExecutor`.

The `CommandExecutor` interface also offers the ability to export data via "out" parameters. Inserted facts, globals and query results can all be returned.

Example 4.27. Out identifiers

    // Set up a list of commands

    List cmds = new ArrayList();

    cmds.add( CommandFactory.newSetGlobal( "list1", new ArrayList(), true ) );

    cmds.add( CommandFactory.newInsert( new Person( "jon", 102 ), "person" ) );

    cmds.add( CommandFactory.newQuery( "Get People" "getPeople" );

    // Execute the list

    ExecutionResults results =

      ksession.execute( CommandFactory.newBatchExecution( cmds ) );

    // Retrieve the ArrayList

    results.getValue( "list1" );

    // Retrieve the inserted Person fact

    results.getValue( "person" );

    // Retrieve the query as a QueryResults instance.

    results.getValue( "Get People" );

#### 4.2.4.8. Marshalling

The `KieMarshallers` is used to marshal and unmarshal KieSessions.

Figure 4.25. KieMarshallers

An instance of the `KieMarshallers` can be retrieved from the `KieServices` and at the simplest the it can be used as follows:

Example 4.28. Simple Marshaller Example

    // ksession is the KieSession

    // kbase is the KieBase

    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    Marshaller marshaller = KieServices.Factory.get().getMarshallers().newMarshaller( kbase );

    marshaller.marshall( baos, ksession );

    baos.close();

However, with marshalling you need more flexibility when dealing with referenced user data. To achieve this we have the `ObjectMarshallingStrategy` interface. Two implementations are provided, but users can implement their own. The two supplied strategies are `IdentityMarshallingStrategy` and `SerializeMarshallingStrategy`. `SerializeMarshallingStrategy` is the default, as used in the example above, and it just calls the `Serializable` or `Externalizable` methods on a user instance. `IdentityMarshallingStrategy` instead creates an integer id for each user object and stores them in a Map, while the id is written to the stream. When unmarshalling it accesses the `IdentityMarshallingStrategy` map to retrieve the instance. This means that if you use the `IdentityMarshallingStrategy`, it is stateful for the life of the Marshaller instance and will create ids and keep references to all objects that it attempts to marshal. Below is he code to use an Identity Marshalling Strategy.

Example 4.29. IdentityMarshallingStrategy

    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    KieMarshallers kMarshallers = KieServices.Factory.get().getMarshallers()

    ObjectMarshallingStrategy oms = kMarshallers.newIdentityMarshallingStrategy()

    Marshaller marshaller =

            kMarshallers.newMarshaller( kbase, new ObjectMarshallingStrategy[]{ oms } );

    marshaller.marshall( baos, ksession );

    baos.close();

For added flexability we can't assume that a single strategy is suitable. Therefore we have added the `ObjectMarshallingStrategyAcceptor` interface that each Object Marshalling Strategy contains. The Marshaller has a chain of strategies, and when it attempts to read or write a user object it iterates the strategies asking if they accept responsability for marshalling the user object. One of the provided implementations is `ClassFilterAcceptor`. This allows strings and wild cards to be used to match class names. The default is "*.*", so in the above example the Identity Marshalling Strategy is used which has a default "*.*" acceptor.

Assuming that we want to serialize all classes except for one given package, where we will use identity lookup, we could do the following:

Example 4.30. IdentityMarshallingStrategy with Acceptor

    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    KieMarshallers kMarshallers = KieServices.Factory.get().getMarshallers()

    ObjectMarshallingStrategyAcceptor identityAcceptor =

            kMarshallers.newClassFilterAcceptor( new String[] { "org.domain.pkg1.*" } );

    ObjectMarshallingStrategy identityStrategy =

            kMarshallers.newIdentityMarshallingStrategy( identityAcceptor );

    ObjectMarshallingStrategy sms = kMarshallers.newSerializeMarshallingStrategy();

    Marshaller marshaller =

            kMarshallers.newMarshaller( kbase,

                                        new ObjectMarshallingStrategy[]{ identityStrategy, sms } );

    marshaller.marshall( baos, ksession );

    baos.close();

Note that the acceptance checking order is in the natural order of the supplied elements.

Also note that if you are using scheduled matches (i.e. some of your rules use timers or calendars) they are marshallable only if, before you use it, you configure your KieSession to use a trackable timer job factory manager as it follows:

Example 4.31. Configuring a trackable timer job factory manager

    KieSessionConfiguration ksconf = KieServices.Factory.get().newKieSessionConfiguration();

    ksconf.setOption(TimerJobFactoryOption.get("trackable"));

    KSession ksession = kbase.newKieSession(ksconf, null);

#### 4.2.4.9. Persistence and Transactions

Longterm out of the box persistence with Java Persistence API (JPA) is possible with Drools. It is necessary to have some implementation of the Java Transaction API (JTA) installed. For development purposes the Bitronix Transaction Manager is suggested, as it's simple to set up and works embedded, but for production use JBoss Transactions is recommended.

Example 4.32. Simple example using transactions

    KieServices kieServices = KieServices.Factory.get();

    Environment env = kieServices.newEnvironment();

    env.set( EnvironmentName.ENTITY_MANAGER_FACTORY,

             Persistence.createEntityManagerFactory( "emf-name" ) );

    env.set( EnvironmentName.TRANSACTION_MANAGER,

             TransactionManagerServices.getTransactionManager() );

    // KieSessionConfiguration may be null, and a default will be used

    KieSession ksession =

            kieServices.getStoreServices().newKieSession( kbase, null, env );

    int sessionId = ksession.getId();

    UserTransaction ut =

      (UserTransaction) new InitialContext().lookup( "java:comp/UserTransaction" );

    ut.begin();

    ksession.insert( data1 );

    ksession.insert( data2 );

    ksession.startProcess( "process1" );

    ut.commit();

To use a JPA, the Environment must be set with both the `EntityManagerFactory` and the `TransactionManager`. If rollback occurs the ksession state is also rolled back, so it is possible continue to use it after a rollback. To load a previously persisted KieSession you'll need the id, as shown below:

Example 4.33. Loading a KieSession

    KieSession ksession =

            kieServices.getStoreServices().loadKieSession( sessionId, kbase, null, env );

To enable persistence several classes must be added to your persistence.xml, as in the example below:

Example 4.34. Configuring JPA

    <persistence-unit name="org.drools.persistence.jpa" transaction-type="JTA">

       <provider>org.hibernate.ejb.HibernatePersistence</provider>

       <jta-data-source>jdbc/BitronixJTADataSource</jta-data-source>

       <class>org.drools.persistence.info.SessionInfo</class>

       <class>org.drools.persistence.info.WorkItemInfo</class>

       <properties>

             <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>

             <property name="hibernate.max_fetch_depth" value="3"/>

             <property name="hibernate.hbm2ddl.auto" value="update" />

             <property name="hibernate.show_sql" value="true" />

             <property name="hibernate.transaction.manager_lookup_class"

                          value="org.hibernate.transaction.BTMTransactionManagerLookup" />

       </properties>

    </persistence-unit>

The jdbc JTA data source would have to be configured first. Bitronix provides a number of ways of doing this, and its documentation should be contsulted for details. For a quick start, here is the programmatic approach:

Example 4.35. Configuring JTA DataSource

    PoolingDataSource ds = new PoolingDataSource();

    ds.setUniqueName( "jdbc/BitronixJTADataSource" );

    ds.setClassName( "org.h2.jdbcx.JdbcDataSource" );

    ds.setMaxPoolSize( 3 );

    ds.setAllowLocalTransactions( true );

    ds.getDriverProperties().put( "user", "sa" );

    ds.getDriverProperties().put( "password", "sasa" );

    ds.getDriverProperties().put( "URL", "jdbc:h2:mem:mydb" );

    ds.init();

Bitronix also provides a simple embedded JNDI service, ideal for testing. To use it add a jndi.properties file to your META-INF and add the following line to it:

Example 4.36. JNDI properties

    java.naming.factory.initial=bitronix.tm.jndi.BitronixInitialContextFactory

### 4.2.5. Build, Deploy and Utilize Examples

The best way to learn the new build system is by example. The source project "drools-examples-api" contains a number of examples, and can be found at github:

https://github.com/droolsjbpm/drools/tree/6.0.x/drools-examples-api

Each example is described below, the order starts with the simplest and most default working it's way up to more complex use cases.

The Deploy use cases here all involve `mvn install`. Remote deployment of jars in Maven is well covered is Maven literature. Utilize refers to the initial act loading the resources and providing access to the KIE runtimes. Where as Run refers to the act of interacting with those runtimes.

#### 4.2.5.1. Default KieSession

- Project: default-kesession.

- Summary: Empty kmodule.xml KieModule on the classpath that includes all resources in a single default KieBase . The example shows the retrieval of the default KieSession from the classpath.

An empty kmodule.xml will produce a single KieBase that includes all files found under resources path, be it DRL, BPMN2, XLS etc. That single KieBase is the default and also includes a single default KieSession. Default means they can be created without knowing their names.

Example 4.37. Author - kmodule.xml

    <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> </kmodule>

Example 4.38. Build and Install - Maven

    mvn install

ks.getKieClasspathContainer() returns the KieContainer that contains the KieBases deployed onto the environment classpath. kContainer.newKieSession() creates the default KieSession. Notice you no longer need to look up the KieBase, in orde to create the KieSession. The KieSession knows which KieBase it's assocaited with, and ues that, which in this case is the default KieBase.

Example 4.39. Utilize and Run - Java

    KieServices ks = KieServices.Factory.get();

    KieContainer kContainer = ks.getKieClasspathContainer();

    KieSession kSession = kContainer.newKieSession();

    kSession.setGlobal("out", out);

    kSession.insert(new Message("Dave", "Hello, HAL. Do you read me, HAL?"));

    kSession.fireAllRules();

#### 4.2.5.2. Named KieSession

- Project: named-kiesession.

- Summary: kmodule.xml that has one named KieBase and one named KieSession. The examples shows the retrieval of the named KieSession from the classpath.

kmodule.xml will produce a single named KieBase, 'kbase1' that includes all files found under resources path, be it DRL, BPMN2, XLS etc. KieSession 'ksession1' is associated with that KieBase and can be created by name.

Example 4.40. Author - kmodule.xml

    <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">

        <kbase name="kbase1">

            <ksession name="ksession1"/>

        </kbase>

    </kmodule>

Example 4.41. Build and Install - Maven

    mvn install

ks.getKieClasspathContainer() returns the KieContainer that contains the KieBases deployed onto the environment classpath. This time the KieSession uses the name 'ksession1'. You do not need to lookup the KieBase first, as it knows which KieBase 'ksession1' is assocaited with.

Example 4.42. Utilize and Run - Java

    KieServices ks = KieServices.Factory.get();

    KieContainer kContainer = ks.getKieClasspathContainer();

    KieSession kSession = kContainer.newKieSession("ksession1");

    kSession.setGlobal("out", out);

    kSession.insert(new Message("Dave", "Hello, HAL. Do you read me, HAL?"));

    kSession.fireAllRules();

#### 4.2.5.3. KieBase Inheritence

- Project: kiebase-inclusion.

- Summary: 'kmodule.xml' demonstrate that one KieBase can include the resources from another KieBase, from another KieModule. In this case it inherits the named KieBase from the 'name-kiesession' example. The included KieBase can be from the current KieModule or any other KieModule that is in the pom.xml dependency list.

kmodule.xml will produce a single named KieBase, 'kbase2' that includes all files found under resources path, be it DRL, BPMN2, XLS etc. Further it will include all the resources found from the KieBase 'kbase1', due to the use of the 'includes' attribute. KieSession 'ksession2' is associated with that KieBase and can be created by name.

Example 4.43. Author - kmodule.xml

    <kbase name="kbase2" includes="kbase1">

        <ksession name="ksession2"/>

    </kbase>

This example requires that the previous example, 'named-kiesession', is built and installed to the local Maven repository first. Once installed it can be included as a dependency, using the standard Maven <dependencies> element.

Example 4.44. Author - pom.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0"

             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

      <modelVersion>4.0.0</modelVersion>

      <parent>

        <groupId>org.drools</groupId>

        <artifactId>drools-examples-api</artifactId>

        <version>6.0.0/version>

      </parent>

      <artifactId>kiebase-inclusion</artifactId>

      <name>Drools API examples - KieBase Inclusion</name>

      <dependencies>

        <dependency>

          <groupId>org.drools</groupId>

          <artifactId>drools-compiler</artifactId>

        </dependency>

        <dependency>

          <groupId>org.drools</groupId>

          <artifactId>named-kiesession</artifactId>

          <version>6.0.0</version>

        </dependency>

      </dependencies>

    </project>

Once 'named-kiesession' is built and installed this example can be built and installed as normal. Again the act of installing, will force the unit tests to run, demonstrating the use case.

Example 4.45. Build and Install - Maven

    mvn install

ks.getKieClasspathContainer() returns the KieContainer that contains the KieBases deployed onto the environment classpath. This time the KieSession uses the name 'ksession2'. You do not need to lookup the KieBase first, as it knows which KieBase 'ksession1' is assocaited with. Notice two rules fire this time, showing that KieBase 'kbase2' has included the resources from the dependency KieBase 'kbase1'.

Example 4.46. Utilize and Run - Java

    KieServices ks = KieServices.Factory.get();

    KieContainer kContainer = ks.getKieClasspathContainer();

    KieSession kSession = kContainer.newKieSession("ksession2");

    kSession.setGlobal("out", out);

    kSession.insert(new Message("Dave", "Hello, HAL. Do you read me, HAL?"));

    kSession.fireAllRules();

    kSession.insert(new Message("Dave", "Open the pod bay doors, HAL."));

    kSession.fireAllRules();

#### 4.2.5.4. Multiple KieBases

- Project: 'multiple-kbases.

- Summary: Demonstrates that the 'kmodule.xml' can contain any number of KieBase or KieSession declarations. Introduces the 'packages' attribute to select the folders for the resources to be included inthe .

kmodule.xml produces 6 different named KieBases. 'kbase1' includes all resources from the KieModule. The other KieBases include resources from other selected folders, via the 'packages' attribute. Note the use wildcard '*' use, to select this package and all packages below it.

Example 4.47. Author - kmodule.xml

    <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">

      <kbase name="kbase1">

        <ksession name="ksession1"/>

      </kbase>

      <kbase name="kbase2" packages="org.some.pkg">

        <ksession name="ksession2"/>

      </kbase>

      <kbase name="kbase3" includes="kbase2" packages="org.some.pkg2">

        <ksession name="ksession3"/>

      </kbase>

      <kbase name="kbase4" packages="org.some.pkg, org.other.pkg">

        <ksession name="ksession4"/>

      </kbase>

      <kbase name="kbase5" packages="org.*">

        <ksession name="ksession5"/>

      </kbase>

      <kbase name="kbase6" packages="org.some.*">

        <ksession name="ksession6"/>

      </kbase>

    </kmodule>

Example 4.48. Build and Install - Maven

    mvn install

Only part of the example is included below, as there is a test method per KieSession, but each one is a repetitino of the other, with just different list expectations.

Example 4.49. Utilize and Run - Java

    @Test

    public void testSimpleKieBase() {

        List<Integer> list = useKieSession("ksession1");

        // no packages imported means import everything

        assertEquals(4, list.size());

        assertTrue( list.containsAll( asList(0, 1, 2, 3) ) );

    }

    //.. other tests for ksession2 to ksession6 here

    private List<Integer> useKieSession(String name) {

        KieServices ks = KieServices.Factory.get();

        KieContainer kContainer = ks.getKieClasspathContainer();

        KieSession kSession = kContainer.newKieSession(name);

        List<Integer> list = new ArrayList<Integer>();

        kSession.setGlobal("list", list);

        kSession.insert(1);

        kSession.fireAllRules();

        return list;

    }

#### 4.2.5.5. KieContainer from KieRepository

- Project: kcontainer-from-repository

- Summary: The project does not contain a kmodule.xml, nor does the pom.xml have any dependencies for other KieModules. Instead the Java code demonstrates the loading of a dynamic KieModule from a maven repository.

The pom.xml must include kie-ci as a depdency, to ensure Maven is available at runtime. As this uses Maven under the hood you can also use the standard Maven settings.xml file.

Example 4.50. Author - pom.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0"

             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

      <modelVersion>4.0.0</modelVersion>

      <parent>

        <groupId>org.drools</groupId>

        <artifactId>drools-examples-api</artifactId>

        <version>6.0.0</version>

      </parent>

      <artifactId>kiecontainer-from-kierepo</artifactId>

      <name>Drools API examples - KieContainer from KieRepo</name>

      <dependencies>

        <dependency>

          <groupId>org.kie</groupId>

          <artifactId>kie-ci</artifactId>

        </dependency>

      </dependencies>

    </project>

Example 4.51. Build and Install - Maven

    mvn install

In the previous examples the classpath KieContainer used. This example creates a dynamic KieContainer as specified by the ReleaseId. The ReleaseId uses Maven conventions for group id, artifact id and version. It also obey's LATEST and SNAPSHOT for versions.

Example 4.52. Utilize and Run - Java

    KieServices ks = KieServices.Factory.get();

    // Install example1 in the local maven repo before to do this

    KieContainer kContainer = ks.newKieContainer(ks.newReleaseId("org.drools", "named-kiesession", "6.0.0-SNAPSHOT"));

    KieSession kSession = kContainer.newKieSession("ksession1");

    kSession.setGlobal("out", out);

    Object msg1 = createMessage(kContainer, "Dave", "Hello, HAL. Do you read me, HAL?");

    kSession.insert(msg1);

    kSession.fireAllRules();

#### 4.2.5.6. Default KieSession from File

- Project: default-kiesession-from-file

- Summary: Dynamic KieModules can also be loaded from any Resource location. The loaded KieModule provides default KieBase and KieSession definitions.

No kmodue.xml file exists. The project 'default-kiesession' must be built first, so that the resulting jar, in the target folder, be be reference as a File.

Example 4.53. Build and Install - Maven

    mvn install

Any KieModule can be loaded from a Resource location and added to the KieRepository. Once in the KieRepository it can be resolved via it's ReleaseId. Note neither Maven or kie-ci are needed here. It will not setup a transitive dependency parent classloader.

Example 4.54. Utilize and Run - Java

    KieServices ks = KieServices.Factory.get();

    KieRepository kr = ks.getRepository();

    KieModule kModule = kr.addKieModule(ks.getResources().newFileSystemResource(getFile("default-kiesession")));

    KieContainer kContainer = ks.newKieContainer(kModule.getReleaseId());

    KieSession kSession = kContainer.newKieSession();

    kSession.setGlobal("out", out);

    Object msg1 = createMessage(kContainer, "Dave", "Hello, HAL. Do you read me, HAL?");

    kSession.insert(msg1);

    kSession.fireAllRules();

#### 4.2.5.7. Named KieSession from File

- Project: named-kiesession-from-file

- Summary: Dynamic KieModules can also be loaded from any Resource location. The loaded KieModule provides named KieBase and KieSession definitions.

No kmodue.xml file exists. The project 'named-kiesession' must be built first, so that the resulting jar, in the target folder, be be reference as a File.

Example 4.55. Build and Install - Maven

    mvn install

Any KieModule can be loaded from a Resource location and added to the KieRepository. Once in the KieRepository it can be resolved via it's ReleaseId. Note neither Maven or kie-ci are needed here. It will not setup a transitive dependency parent classloader.

Example 4.56. Utilize and Run - Java

    KieServices ks = KieServices.Factory.get();

    KieRepository kr = ks.getRepository();

    KieModule kModule = kr.addKieModule(ks.getResources().newFileSystemResource(getFile("named-kiesession")));

    KieContainer kContainer = ks.newKieContainer(kModule.getReleaseId());

    KieSession kSession = kContainer.newKieSession("ksession1");

    kSession.setGlobal("out", out);

    Object msg1 = createMessage(kContainer, "Dave", "Hello, HAL. Do you read me, HAL?");

    kSession.insert(msg1);

    kSession.fireAllRules();

#### 4.2.5.8. KieModule with Dependant KieModule

- Project: kie-module-form-multiple-files

- Summary: Programmatically provide the list of dependant KieModules, without any Maven to resolve anything.

No kmodue.xml file exists. The projects 'named-kiesession' and 'kiebase-include' must be built first, so that the resulting jars, in the target folders, be be reference as Files.

Example 4.57. Build and Install - Maven

    mvn install

Creates two resources. One is for the main KieModule 'exRes1' the other is for the dependency 'exRes2'. Even though kie-ci is not present and thus Maven is not there to resolve the dependencies, this shows how you can manually specify the dependency KieModuels, for the vararg.

Example 4.58. Utilize and Run - Java

    KieServices ks = KieServices.Factory.get();

    KieRepository kr = ks.getRepository();

    Resource ex1Res = ks.getResources().newFileSystemResource(getFile("kiebase-inclusion"));

    Resource ex2Res = ks.getResources().newFileSystemResource(getFile("named-kiesession"));

    KieModule kModule = kr.addKieModule(ex1Res, ex2Res);

    KieContainer kContainer = ks.newKieContainer(kModule.getReleaseId());

    KieSession kSession = kContainer.newKieSession("ksession2");

    kSession.setGlobal("out", out);

    Object msg1 = createMessage(kContainer, "Dave", "Hello, HAL. Do you read me, HAL?");

    kSession.insert(msg1);

    kSession.fireAllRules();

    Object msg2 = createMessage(kContainer, "Dave", "Open the pod bay doors, HAL.");

    kSession.insert(msg2);

    kSession.fireAllRules();

#### 4.2.5.9. Programaticaly build a Simple KieModule with Defaults

- Project: kiemoduelmodel-example

- Summary: Programmaticaly buid a KieModule from just a single file. The pom and models are all defaulted. This is the quickest out of the box approach, but should not be added to a Maven repository.

Example 4.59. Build and Install - Maven

    mvn install

This programmatically builds a KieModule. It populates the model that represents the ReleaseId and kmodule.xml, as well as added the resources tht. A pom.xml is generated from the ReleaseId.

Example 4.60. Utilize and Run - Java

    KieServices ks = KieServices.Factory.get();

    KieRepository kr = ks.getRepository();

    KieFileSystem kfs = ks.newKieFileSystem();

    kfs.write("src/main/resources/org/kie/example5/HAL5.drl", getRule());

    KieBuilder kb = ks.newKieBuilder(kfs);

    kb.buildAll(); // kieModule is automatically deployed to KieRepository if successfully built.

    if (kb.getResults().hasMessages(Level.ERROR)) {

        throw new RuntimeException("Build Errors:\n" + kb.getResults().toString());

    }

    KieContainer kContainer = ks.newKieContainer(kr.getDefaultReleaseId());

    KieSession kSession = kContainer.newKieSession();

    kSession.setGlobal("out", out);

    kSession.insert(new Message("Dave", "Hello, HAL. Do you read me, HAL?"));

    kSession.fireAllRules();

#### 4.2.5.10. Programaticaly build a KieModule using Meta Models

- Project: kiemoduelmodel-example

- Summary: Programmaticaly buid a KieModule, by creating it's kmodule.xml meta models resources..

Example 4.61. Build and Install - Maven

    mvn install

This programmatically builds a KieModule. It populates the model that represents the ReleaseId and kmodule.xml, as well as added the resources tht. A pom.xml is generated from the ReleaseId.

Example 4.62. Utilize and Run - Java

    KieServices ks = KieServices.Factory.get();

    KieFileSystem kfs = ks.newKieFileSystem();

    Resource ex1Res = ks.getResources().newFileSystemResource(getFile("named-kiesession"));

    Resource ex2Res = ks.getResources().newFileSystemResource(getFile("kiebase-inclusion"));

    ReleaseId rid = ks.newReleaseId("org.drools", "kiemodulemodel-example", "6.0.0-SNAPSHOT");

    kfs.generateAndWritePomXML(rid);

    KieModuleModel kModuleModel = ks.newKieModuleModel();

    kModuleModel.newKieBaseModel("kiemodulemodel")

                .addInclude("kiebase1")

                .addInclude("kiebase2")

                .newKieSessionModel("ksession6");

    kfs.writeKModuleXML(kModuleModel.toXML());

    kfs.write("src/main/resources/kiemodulemodel/HAL6.drl", getRule());

    KieBuilder kb = ks.newKieBuilder(kfs);

    kb.setDependencies(ex1Res, ex2Res);

    kb.buildAll(); // kieModule is automatically deployed to KieRepository if successfully built.

    if (kb.getResults().hasMessages(Level.ERROR)) {

        throw new RuntimeException("Build Errors:\n" + kb.getResults().toString());

    }

    KieContainer kContainer = ks.newKieContainer(rid);

    KieSession kSession = kContainer.newKieSession("ksession6");

    kSession.setGlobal("out", out);

    Object msg1 = createMessage(kContainer, "Dave", "Hello, HAL. Do you read me, HAL?");

    kSession.insert(msg1);

    kSession.fireAllRules();

    Object msg2 = createMessage(kContainer, "Dave", "Open the pod bay doors, HAL.");

    kSession.insert(msg2);

    kSession.fireAllRules();

    Object msg3 = createMessage(kContainer, "Dave", "What's the problem?");

    kSession.insert(msg3);

    kSession.fireAllRules();

- PrevPart II. KIE
- Top of page
- Front page
- NextPart III. Drools Runtime and Language