Chapter 3. User Guide

Table of Contents

Building
Building using Code
Building using Configuration and the ChangeSet XML
Deploying
KnowledgePackage and Knowledge Definitions
KnowledgeBase
In-Process Building and Deployment
Building and Deployment in Separate Processes
StatefulknowledgeSessions and KnowledgeBase Modifications
KnowledgeAgent
Running
KnowledgeBase
StatefulKnowledgeSession
KnowledgeRuntime
Agenda
Event Model
KnowledgeRuntimeLogger
StatelessKnowledgeSession
Pipeline
Commands and the CommandExecutor
Marshalling
Persistence and Transactions

Building

Figure 3.1. org.drools.builder

org.drools.builder

Building using Code

The KnowledgeBuilder is responsible for taking source files, such as a DRL file or an Excel file, and turning them into a Knowledge Package of rule and process definitions which a Knowledge Base can consume. An object of the class ResourceType indicates the type of resource it is being asked to build.

The ResourceFactory provides capabilities to load resources from a number of sources, such as Reader, ClassPath, URL, File, or ByteArray. Binaries, such as decision tables (Excel .xls files), should not use a Reader based resource handler, which is only suitable for text based resources.

Figure 3.2. KnowledgeBuilder

KnowledgeBuilder

The KnowlegeBuilder is created using the KnowledgeBuilderFactory.

Figure 3.3. KnowledgeBuilderFactory

KnowledgeBuilderFactory

A KnowledgeBuilder can be created using the default configuration.

Example 3.1. Creating a new KnowledgeBuilder

KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();

A configuration can be created using the KnowledgeBuilderFactory. This allows the behavior of the Knowledge Builder to be modified. The most common usage is to provide a custom class loader so that the KnowledgeBuilder object can resolve classes that are not in the default classpath. The first parameter is for properties and is optional, i.e., it may be left null, in which case the default options will be used. The options parameter can be used for things like changing the dialect or registering new accumulator functions.

Example 3.2. Creating a new KnowledgeBuilder with a custom ClassLoader

KnowledgeBuilderConfiguration kbuilderConf = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(null, classLoader );
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(kbuilderConf);

Resources of any type can be added iteratively. Below, a DRL file is added. Unlike Drools 4.0 Package Builder, the Knowledge Builder can now handle multiple namespaces, so you can just keep adding resources regardless of namespace.

Example 3.3. Adding DRL Resources

kbuilder.add( ResourceFactory.newFileResource( "/project/myrules.drl" ),
              ResourceType.DRL);

It is best practice to always check the hasErrors() method after an addition. You should not add more resources or retrieve the Knowledge Packages if there are errors. getKnowledgePackages() returns an empty list if there are errors.

Example 3.4. Validating

if( kbuilder.hasErrors() ) {
    System.out.println( kbuilder.getErrors() );
    return;
}

When all the resources have been added and there are no errors the collection of Knowledge Packages can be retrieved. It is a Collection because there is one Knowledge Package per package namespace. These Knowledge Packages are serializable and often used as a unit of deployment.

Example 3.5. Getting the KnowledgePackages

Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();

The final example puts it all together.

Example 3.6. Putting it all together

KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
if( kbuilder.hasErrors() ) {
    System.out.println( kbuilder.getErrors() );
    return;
}

KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newFileResource( "/project/myrules1.drl" ),
              ResourceType.DRL);
kbuilder.add( ResourceFactory.newFileResource( "/project/myrules2.drl" ),
              ResourceType.DRL);

if( kbuilder.hasErrors() ) {
    System.out.println( kbuilder.getErrors() );
    return;
}

Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();

Building using Configuration and the ChangeSet XML

Instead of adding the resources to create definitions programmatically it is also possible to do it by configuration, via the ChangeSet XML. The simple XML file supports three elements: add, remove, and modify, each of which has a sequence of <resource> subelements defining a configuration entity. The following XML schema is not normative and intended for illustration only.

Example 3.7. XML Schema for ChangeSet XML (not normative)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns="http://drools.org/drools-5.0/change-set"
           targetNamespace="http://drools.org/drools-5.0/change-set">

  <xs:element name="change-set" type="ChangeSet"/>

  <xs:complexType name="ChangeSet">
    <xs:choice maxOccurs="unbounded">
      <xs:element name="add"    type="Operation"/>
      <xs:element name="remove" type="Operation"/>
      <xs:element name="modify" type="Operation"/>
    </xs:choice>
  </xs:complexType>

  <xs:complexType name="Operation">
    <xs:sequence>
      <xs:element name="resource" type="Resource"
                  maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="Resource">
    <xs:sequence>
      
      <xs:element name="decisiontable-conf" type="DecTabConf"
                  minOccurs="0"/>
    </xs:sequence>
    
    <xs:attribute name="source" type="xs:string"/>
    <xs:attribute name="type"   type="ResourceType"/>
  </xs:complexType>

  <xs:complexType name="DecTabConf">
    <xs:attribute name="input-type"     type="DecTabInpType"/>
    <xs:attribute name="worksheet-name" type="xs:string"
                  use="optional"/>
  </xs:complexType>

  
  <xs:simpleType name="ResourceType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="DRL"/>
      <xs:enumeration value="XDRL"/>
      <xs:enumeration value="DSL"/>
      <xs:enumeration value="DSLR"/>
      <xs:enumeration value="DRF"/>
      <xs:enumeration value="DTABLE"/>
      <xs:enumeration value="PKG"/>
      <xs:enumeration value="BRL"/>
      <xs:enumeration value="CHANGE_SET"/>
    </xs:restriction>
  </xs:simpleType>

  
  <xs:simpleType name="DecTabInpType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="XLS"/>
      <xs:enumeration value="CSV"/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>

Currently only the add element is supported, but the others will be implemented to support iterative changes. The following example loads a single DRL file.

Example 3.8. Simple ChangeSet XML

<change-set xmlns='http://drools.org/drools-5.0/change-set'
            xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
            xs:schemaLocation='http://drools.org/drools-5.0/change-set.xsd' >
   <add>
      <resource source='file:/project/myrules.drl' type='DRL' />
   </add>
</change-set>

Notice the file: prefix, which signifies the protocol for the resource. The Change Set supports all the protocols provided by java.net.URL, such as "file" and "http", as well as an additional "classpath". Currently the type attribute must always be specified for a resource, as it is not inferred from the file name extension. Using the ClassPath resource loader in Java allows you to specify the Class Loader to be used to locate the resource but this is not possible from XML. Instead, the Class Loader will default to the one used by the Knowledge Builder unless the ChangeSet XML is itself loaded by the ClassPath resource, in which case it will use the Class Loader specified for that resource.

Currently you still need to use the API to load that ChangeSet, but we will add support for containers such as Spring in the future, so that the process of creating a Knowledge Base can be done completely by XML configuration. Loading resources using an XML file couldn't be simpler, as it's just another resource type.

Example 3.9. Loading the ChangeSet XML

kbuilder.add( ResourceFactory.newUrlResource( url ), ResourceType.CHANGE_SET );

ChangeSets can include any number of resources, and they even support additional configuration information, which currently is only needed for decision tables. Below, the example is expanded to load rules from a http URL location, and an Excel decision table from the classpath.

Example 3.10. ChangeSet XML with resource configuration

 <change-set xmlns='http://drools.org/drools-5.0/change-set'
             xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
             xs:schemaLocation='http://drools.org/drools-5.0/change-set.xsd' >
  <add>
       <resource source='http:org/domain/myrules.drl' type='DRL' />
       <resource source='classpath:data/IntegrationExampleTest.xls' type="DTABLE">
           <decisiontable-conf input-type="XLS" worksheet-name="Tables_2" />
       </resource>
   </add>
 </change-set>

The ChangeSet is especially useful when working with a Knowledge Agent, as it allows for change notification and automatic rebuilding of the Knowledge Base, which is covered in more detail in the section on the Knowledge Agent, under Deploying.

Directories can also be specified, to add all resources in that folder. Currently it is expected that all resources in that folder are of the same type. If you use the Knowledge Agent it will provide a continous scanning for added, modified or removed resources and rebuild the cached Knowledge Base. The KnowledgeAgent provides more information on this.

Example 3.11. ChangeSet XML which adds a directory's contents

<change-set xmlns='http://drools.org/drools-5.0/change-set'
            xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
            xs:schemaLocation='http://drools.org/drools-5.0/change-set.xsd' >
   <add>
      <resource source='file:/projects/myproject/myrules' type='DRL' />
   </add>
</change-set>