Quarking Drools: How we turned a 13-year-old Java project into a first-class serverless component

“The question of whether a computer can think is no more interesting
than the question of whether a submarine can swim.”
– Edsger W. Dijkstra
Rule-based artificial intelligence (AI) is often overlooked, possibly because people think it’s only useful in heavyweight enterprise software products. However, that’s not necessarily true. Simply put, a rule engine is just a piece of software that allows you to separate domain and business-specific constraint from the main application flow. We are part of the team developing and maintaining Drools—the world’s most popular open source rule engine and part of Red Hat—and, in this article, we will describe how we are changing Drools to make it part of the cloud and serverless revolution.

Technical overview

Our main goal was to make the core of the rule engine lighter, isolated, easily portable across different platforms, and well-suited to run in a container. The software development landscape has changed a lot in the past 20 years. We are moving more and more toward a polyglot world, which is one reason why we are working to make our technology work across a lot of different platforms. This is also why we started looking into GraalVM, the new Oracle Labs polyglot virtual machine (VM) ecosystem, consisting of:
  • A polyglot VM runtime, alternative to the Java virtual machine (JVM) with a just-in-time (JIT) compiler that improves efficiency and speed of applications over traditional HotSpot. This is also the “proper” GraalVM.
  • A framework to write efficient dynamic programming languages (e.g., JavaScript, Python, and R) and to mix and match them (Truffle).
  • A tool to compile programs ahead-of-time (AOT) into a native executable.
Meanwhile at Red Hat, another team was already experimenting with GraalVM and native binary generation for application development. This effort has been realized in a new project you may have heard of called Quarkus. The Quarkus project is a best-of-breed Java stack that works on good old JVM but is also especially tailored for GraalVM, native binary compilation, and cloud-native application development.
GraalVM is an amazing tool, but it also comes with some (understandable) limitations. Thus, Quarkus is designed to integrate seamlessly with GraalVM and native image generation, as well as provide useful utilities to overcome any related limitations. In particular, Drools used to make extensive use of dynamic class generation, class-loading, and quite a bit of reflection. To produce fast, efficient, and small native executables, Graal performs aggressive inlining and dead-code elimination, and it operates under a closed-world assumption: that is, the compiler removes any references to class and methods that cannot be statically reachable in the code. In other words, unrestricted reflective calls and dynamic class loading are a no-go. Although this may at first sound like a showstopper, here we will document in detail how we modified the core of Drools to overcome such limitations, and we will explain why such limitations are not evil and can be liberating.

The Executable Model

In a rule engine, facts are inserted into a working memory. Rules describe actions to take when certain constraints over the facts that are inserted into the working memory become true. For instance, the sentence “when the sun goes down : turn on the lights” expresses a rule over the sun. The fact is that the sun is going down. The action is to turn on the lights. In a rule engine, we insert the “sun is going down” fact inside the working memory. When we fire the rules, the action of turning on the lights will execute.
A rule definition has the form
constraintsconsequence
The constraints part, also called the left-hand side of the rule, describes the constraints that activate the rule and make it ready to fire; the consequence part, also called the right-hand side of the rule, contains the action that rule will take when the rule is fired.
In Drools, a rule is written using the Drools Rule Language (in short, DRL), and it has the form:
rule R1 when
   $r : Result()                               // constraints
   $p : Person( age >= 18 )     
then
   $r.setValue( $p.getName() + " can drink");  // consequence
end
Constraints are written using a form of pattern-matching over the data (Java objects) that is inserted into the working memory. Actions are basically a block of Java code with a few Drools-specific extensions.
Historically, the DRL used to be a dynamic language that was interpreted at runtime by the Drools engine. In particular, the pattern matching syntax had a major drawback: it made extensive use of reflection unless the engine detected a constraint was “hot” enough for further optimization; that is, if it had evaluated a certain number of times; in that case the engine would compile it into bytecode on-the-fly.
About one year ago, for performance reasons, we decided to go away with runtime reflection and dynamic code generation and completed the implementation of what we called the Drools Executable Model, providing a pure Java-based representation of a rule set, together with a convenient Java DSL to programmatically define such model.
To give an idea of how this Java API looks, like let’s consider again the simple Drools rule reported above. The rule will fire if the working memory contains any Result instance and any instance of Person where the age field is greater or equal to 18. The consequence is to set the value of the Result object to a String saying that the person can drink. The equivalent rule expressed with the executable model API looks like the following (pretty-printed for readability):
var r = declarationOf(Result.class, "$r");
var p = declarationOf(Person.class, "$p");
var rule =
   rule("com.example", "R1").build(
         pattern(r),
         pattern(p).expr("e", p -> p.getAge() >= 18),
         alphaIndexedBy(int.class, GREATER_OR_EQUAL, 1, this::getAge, 18),
         reactOn("age")),
    on(p, r).execute(($p, $r) ->
         $r.setValue($p.getName() + " can drink")));
As you can see, this representation is more verbose and harder to understand, partly because of the Java syntax, but mostly because it explicitly contains lots of details, such as the specification of how Drools should internally index a given constraint, which was implicit in the corresponding DRL. We did this on purpose because we wanted a totally explicit rule representation that did not require any convoluted inference or reflection sorcery. However, we knew it would be crazy to ask users to be aware of all such intricate details, so we wrote a compiler to translate DRL into the equivalent Java code. We achieved this using JavaParser, a really nice open source library that allows to parse, modify, and generate any Java source code through a convenient API.
In all honesty, when we designed and implemented the executable model, we didn’t have strictly GraalVM in mind. We simply wanted an intermediate and pure Java representation of the rule that could be efficiently interpreted and executed by the engine. Yet, by completely avoiding reflection and dynamic code generation,  the executable model was key to allowing us to support native binary generation with Graal. For instance, because the new model expresses all constraints as lambda predicates, we don’t need to optimize the constraints evaluators through bytecode generation and dynamic classloading, which are totally forbidden in native image generation.
The design and implementation of executable model taught us an important lesson in the process of making Drools compatible with Graal: any limitation can be overcome with a sufficient amount of code generation. We will further discuss this in the next section.

Overcoming other Graal limitations

Having a plain Java model of a Drools rule base was a very good starting point, but more work was needed to make our project compatible with native binary generation.
The executable model makes reflection largely unnecessary; however, our engine still needs reflection for one last feature called property reactivity. Our plans are to get rid of reflection altogether, but, because the change is nontrivial, for this time we resorted to a handy feature of the binary image compiler. This feature does support a form of reflection, provided that we can declare upfront the classes we will need to reflect upon at runtime. This can be supplied by providing a JSON descriptor file to the compiler, or, if you are using Quarkus, you can just annotate the domain classes. For instance, in the rule shown above, our domain classes would be Result and Person. Then we can write:
[
 {
    "name" : "org.drools.simple.project.Person",
    "allPublicMethods" : true
 },
 {
    "name" : "org.drools.simple.project.Result",
    "allPublicMethods" : true
 }
]
Then, we can instruct the native binary compiler with the flag
-H:ReflectionConfigurationFiles=reflection.json
We segregated other redundant reflection trickery to a dynamic module and implemented an alternative static version of the same components that users can choose to import into their project. This approach is especially useful for binary image generation, but it has benefits for regular use cases as well. In particular, avoiding reflection and dynamic loading can result in faster startup time and improved run-time.
At startup time, Drools projects read an XML descriptor called the kmodule, where the user declaratively defines the configuration of the project. Usually, we parse this XML file and load it into memory, but our current XStream-based parser uses a lot of reflection; so, first, we can load the XML with an alternative strategy that avoids reflection. However, we can go further: if we can guarantee that the in-memory representation of the XML will never change across runs, and we can afford to run a quick code-generation phase before repackaging a project for deployment, then we can avoid loading the XML at each boot-up altogether. In fact, we are now able to translate the XML file into a class file that will be loaded at startup time, like any other hand-coded class. Here’s a comparison of the XML with a snippet of the generated code (again, pretty-printed for readability). The generated code is more verbose because it makes explicit all of the configuration defaults.
<kbase name="simpleKB"
       packages="org.drools.simple.project">
  <ksession name="simpleKS" default="true"/>
</kbase>
var m = KieServices.get().newKieModuleModel();
var kb = m.newKieBaseModel("simpleKB");
kb.setEventProcessingMode(CLOUD);
kb.addPackage("org.drools.simple.project");
var ks = kb.newKieSessionModel("simpleKS");
ks.setDefault(true);
ks.setType(STATEFUL);
ks.setClockType(ClockTypeOption.get("realtime"));
Another issue with startup time is dynamic classpath scanning. Drools supports alternate ways to take decisions other than DRL-based rules, such as decision-tables, the Decision Model and Notation (DMN) or predictive models using the Predictive Model Markup Language (PMML). Such extensions are implemented as dynamically loadable modules, that are hooked into the core engine by scanning the classpath at boot-time. Although this is extremely flexible, it is not essential: even in this case, we can avoid runtime classpath scanning and provide static wiring of the required components either by generating code at build-time, or by providing an explicit API to end users to hook components manually. We resorted to provide a pre-built static module with a minimal core.
private Map<Class<?>, Object> serviceMap = new HashMap<>();
private void wireServices() {
  serviceMap.put(ServiceInterface.class,
                 Class.forName("org.drools.ServiceImpl").newInstance());
  // … more services here
}
Note that, although here we are using Class.forName(), the compiler is smart enough to recognize the constant and substitute it with an actual constructor. Of course, it is possible to simplify this further by generating a chain of if statements.
Finally, we tied everything together by getting rid of the last few pre-executable model leftovers: the legacy Drools class-loader. This was the culprit behind the following apparently cryptic error message:
Error: unsupported features in 2 methods
Detailed message:
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException:
Unsupported method java.lang.ClassLoader.defineClass(String, byte[], int, int, ProtectionDomain)
is reachable: The declaring class of this element has been substituted, but this element is not
present in the substitution class
To diagnose the issue, you can add the option --report-unsupported-elements-at-runtime. The
unsupported element is then reported at run time when it is accessed the first time.
Trace:
       at parsing org.drools.dynamic.common.DynamicComponentsSupplier$DefaultByteArrayClassLoader.defineClass(DynamicComponentsSupplier.java:49)
Call path from entry point to org.drools.dynamic.common.DynamicComponentsSupplier$DefaultByteArrayClassLoader.defineClass(String, byte[], ProtectionDomain):
Really, however, the message is pretty clear: our custom class-loader is able to dynamically define a class, which is useful when you generate bytecode at run-time. But, if the codebase relies completely on the executable model, we can avoid this altogether, so we isolated the legacy class-loader into the dynamic module.
This is the last step that was necessary to successfully generate a native image of our simple test project, and the results exceeded our expectations, thereby confirming that the time and efforts we spent in this experiment were well invested. Indeed, executing the main class of our test case with a normal JVM takes 43 milliseconds with a occupation of 73M of memory. The corresponding native image generated by Graal lasted is timed at less than 1 millisecond and uses only 21M of memory.

Integrating with Quarkus

Once we had a first version of Drools compatible with Graal native binary generation, the next natural step was to start leveraging the features provided by Quarkus and try to create a simple web service with it. We noticed that Quarkus offers a different and simpler mechanism to let the compiler know that we need reflection on a specific class. In fact, instead of having to declare this in a JSON file as before, you can annotate the class of your domain model as follows:
@RegisterForReflection
public class Person { … }

We also decided to go one small step forward with our code generation machinery. In particular, we added one small interface to Drools code
public interface KieRuntimeBuilder {
    KieSession newKieSession();
    KieSession newKieSession(String sessionName);
}

so that when the Drools compiler creates the executable model from the DRL files it also generates an implementation of this class. This implementation has the purpose of supplying a Drools session automatically configured with the rules and the parameters defined by the user.
After that, we were ready to put both dependency injection and REST support provided by Quarkus to work, and we developed a simple web service exercising the Drools runtime.
@Path("/candrink/{name}/{age}")
public class CanDrinkResource {

    @Inject
    KieRuntimeBuilder runtimeBuilder;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String canDrink( @PathParam("name") String name,
                            @PathParam("age") int age ) {

       KieSession ksession = runtimeBuilder.newKieSession();

       Result result = new Result();
       ksession.insert(result);
       ksession.insert(new Person( name, age ));
       ksession.fireAllRules();

       return result.toString();
    }
}

The example is straightforward enough to not require any further explanation and is fully deployable as a microservice in an OpenShift cluster. Thanks to the extremely low startup time—due to the work we did on Drools and the low overhead of Quarkus—this microservice is fast enough to be deployable in a KNative cloud. You can find the full source code on GitHub.

Introducing Submarine

These days, rule engines are seldom a matter of discussion. This is because they just work. A rule engine is not necessarily antithetical to a cloud environment, but work might be needed to fit the new paradigm. This was the story of our journey. We started with courage and curiosity. In the next few months, we will push this work forward to become more than a simple prototype, to realize a complete suite of business automation tools ready for the cloud. The name of the initiative is Submarine, from the famous Dijkstra quote. So, sit tight, and get ready to dive in.

This article has been originally published on the Red Hat Developer blog here

Workbench is now Business Central!

5 years ago, on November 2013 we released 6.0.0.Final, that included the first version of the Workbench. It has been a long journey so far, but today we’re announcing that we’re retiring the Workbench brand and officially adopting Business Central as the new brand!

Historical Context

The KIE group has been developing web tooling for more than a decade now. The first public release that shipped a browser based tool was 5.0.1 (May of 2009), but its R&D started way before that.
Tip
KIE stands for Knowledge Is Everything, and it is pronounced exactly the word key in English: /kē/ .
The first experiments of a web-based tool to manage a central repository for business rules that provided an intuitive user interface to create and package rules started back in September 2006 as jbrms. After a couple of years, it was renamed to Guvnor, and this is the name that would become known as the official name of our first web tooling.
guvnor
Figure 1. Guvnor Guided Rule Editor User Interface.
The next generation that became known as Workbench started its R&D in May of 2012 with multiple goals and challenges that could be summarized in the following major two key points:
  • A modular, plug-in based, composable tooling, to avoid the single project/repo that Guvnor became over the years
  • A Virtual File System based storage, to avoid getting stuck with a technology like JCR
workbench
Figure 2. Workbench Original NSEW Compass Drag-and-Drop
If you’re feeling nostalgic, you can play this video, and get back to May of 2013, a few months before the release. But if you have time, and want to see how our fresh released second generation looked like in practice, you have a full playlist.

Evolution

The Workbench has been distributed in two flavors: KIE Drools Workbench and KIE Workbench. Initially, the KIE Workbench used to be shipped with an embedded jBPM engine, what made the distributions significantly different. However, with the KIE-Server release and the engine unification, the embedded jBPM engine was removed from Workbench, and the differences between the two distros became just a matter of show/hide some user interface items.
It’s also clear that the current Workbench has very little in common with its original format. Over the years it not only get more polished and stable, but the target audience has evolved from a developer focused to a collaborative platform between practitioners and developers.
Based on the above facts and also looking for a more concise branding strategy a decision was made: unify the distributions and re-brand it as Business Central!

Business Central

So what’s in the new name? The major positive impact is that we have now a single distribution and terminology to reference the KIE group web tooling, that also unifies the product and community terminology.
Here’s a quick walkthrough of the changes you’ll see in the new Business Central:
business-central

Profiles and Entitlements

By default Business Central bootstrap with all the features enabled, that includes Drools, OptaPlanner, and jBPM. However, for those that are not taking advantage of our jBPM engine, we provide in settings a Profiles option that allows admins to adjust Business Central to display only the relevant profile to your needs.
The default profile can be also be defined in the startup using the org.kie.workbench.profile environment variable with the following possible values:
  • FULL
  • PLANNER_AND_RULES
  • FORCE_FULL
  • FORCE_PLANNER_AND_RULES
The main difference between the “FORCE_” values is that it will hide the settings configuration, forcing the chosen profile.

Conclusion

After five years, the KIE group has decided that was time to retire the Workbench brand. Our web tooling evolved quite a lot and the use of the word Workbench, a common term for developers, didn’t reflect the current state of it.
The consolidation and re-branding to Business Central aims to provide a clear message about its targeted audience with a concise communication strategy. If you’re interested in giving it a try, Business Central is available to download today!

The Drools Executable Model is alive

Overview

The purpose of the executable model is to provide a pure Java-based representation of a rule set, together with a convenient Java DSL to programmatically create such model. The model is low level and designed for the user to provide all the information it needs, such as the lambda’s for the index evaluation. This keeps it fast and avoids building in too many assumptions at this level. It is expected higher level representations can layer on in the future, that may be more end-user focused. This work also highly compliments the unit work, which provides a java-oriented way to provide data and control orchestration.

Details

This model is generic enough to be independent from Drools but can be compiled into a plain Drools knowledge base. For this reason the implementation of the executable model has been split in 2 subprojects:

  1. drools-canonical-model is the canonical representation of a rule set model which is totally independent from Drools
  2. drools-model-compiler compiles the canonical model into Drools internal data structures making it executable by the engine

The introduction of the executable model brings a set of benefits in different areas:

  • Compile time: in Drools 6 a kjar contained the list of drl files and other Drools artifacts defining the rule base together with some pre generated classes implementing the constraints and the consequences. Those drl files needed to be parsed and compiled from scratch, when the kjar is downloaded from the Maven repository and installed in a KieContainer, making this process quite slow especially for large rules sets. Conversely it is now possible to package inside the kjar the Java classes implementing the executable model of the project rule base and recreate the KieContainer and its KieBases out of it in a much faster way. The kie-maven-plugin automatically generates the executable model sources from the drl files during the compilation process.
  • Runtime: in the executable model all constraints are defined as Java lambda expressions. The same lambdas are also used for constraints evaluation and this allows to get rid of both mvel for interpreted evaluation and the jitting process transforming the mvel-based constraints in bytecode, resulting in a slow warming up process.
  • Future research: the executable model will allow to experiment new features of the rule engine without the need of encoding them in the drl format and modify the drl parser to support them. 

    Executable Model DSLs

    One goal while designing the first iteration of the DSL for the executable model was to get rid of the notion of pattern and to consider a rule as a flow of expressions (constraints) and actions (consequences). For this reason we called it Flow DSL. Some examples of this DSL are available here.
    However after having implemented the Flow DSL it became clear that the decision of avoiding the explicit use of patterns obliged us to implement some extra-logic that had both a complexity and a performance cost, since in order to properly recreate the data structures expected by the Drools compiler it is necessary to put together the patterns out of those apparently unrelated expressions.
    For this reason it has been decided to reintroduce the patterns in a second DSL that we called Pattern DSL. This allowed to bypass that algorithm grouping expressions that has to fill an artificial semantic gap and that is also time consuming at runtime.
    We believe that both DSLs are valid for different use cases and then we decided to keep and support both. In particular the Pattern DSL is safer and faster (even if more verbose) so this will be the DSL that will be automatically generated when creating a kjar through the kie-maven-plugin. Conversely the Flow DSL is more succinct and closer to the way how an user may want to programmatically define a rule in Java and we planned to make it even less verbose by generating in an automatic way through a post processor the parts of the model defining the indexing and property reactivity. In other terms we expect that the Pattern DSL will be written by machines and the Flow DSL eventually by human.

    Programmatic Build

    As evidenced by the test cases linked in the former section it is possible to programmatically define in Java one or more rules and then add them to a Model with a fluent API

    Model model = new ModelImpl().addRule( rule );

    Once you have this model, which as explained is totally independent from Drools algorithms and data structures, it’s possible to create a KieBase out of it as it follows

    KieBase kieBase = KieBaseBuilder.createKieBaseFromModel( model );

    Alternatively, it is also possible to create an executable model based kieproject by starting from plain drl files, adding them to a KieFileSystem as usual

    KieServices ks = KieServices.Factory.get();
    KieFileSystem kfs = ks.newKieFileSystem()
    .write( "src/main/resources/r1.drl", createDrl( "R1" ) );
    KieBuilder kieBuilder = ks.newKieBuilder( kfs );

    and then building the project using a new overload of the buildAll() method that accepts a class specifying which kind of project you want to build

    kieBuilder.buildAll( ExecutableModelProject.class );

    Doing so the KieBuilder will generate the executable model (based on the Pattern DSL) and then the resulting KieSession

    KieSession ksession = ks.newKieContainer(ks.getRepository()
    .getDefaultReleaseId())
    .newKieSession();

    will work with lambda expression based constraint as described in the first section of this document. In the same way it is also possible to generate the executable model from the Flow DSL by passing a different project class to the KieBuilder

    kieBuilder.buildAll( ExecutableModelFlowProject.class );

    but, for what explained when discussing the 2 different DSLs, it is better to use the pattern-based one for this purpose.

    Kie Maven Plugin

    In order to generate a kjar embedding the executable model using the kie-maven-plugin it is necessary to add the dependencies related to the two formerly mentioned projects implementing the model and its compiler in the pom.xml file:

    <dependencies>
     <dependency>
       <groupId>org.drools</groupId>
       <artifactId>drools-model-compiler</artifactId>
     </dependency>
     <dependency>
       <groupId>org.drools</groupId>
       <artifactId>drools-canonical-model</artifactId>
     </dependency>
    </dependencies>

    also add the plugin to the plugin section

    <build>
     <plugins>
       <plugin>
         <groupId>org.kie</groupId>
         <artifactId>kie-maven-plugin</artifactId>
         <version>${project.version}</version>
         <extensions>true</extensions>
       </plugin>
     </plugins>
    </build>

    An example of a pom.xml file already prepared to generate the executable model is available here. By default the kie-maven-plugin still generates a drl based kjar, so it is necessary to run the plugin with the following argument:

    -DgenerateModel=<VALUE>

    Where <VALUE> can be one of three values:

    YES
    NO
    WITHDRL

    Both YES and WITHDRL will generate and add to the kjar use the Java classes implementing the executable model corresponding to the drl files in the original project with difference that the first will exclude the drl files from the generated kjar, while the second will also add them. However in this second case the drl files will play only a documentation role since the KieBase will be built from the executable model regardless.

    Future developments

    As anticipated one of the next goal is to make the DSLs, especially the flow one, more user friendly, in particular generating with a post-processor all the parts that could be automatically inferred, like the ones related to indexes and property reactivity.
    Orthogonally from the executable model we improved the modularity and orchestration of rules especially through the work done on rule units, This focus around pojo-ification compliments this direction of research around pure java DSLs and we already have a few simple examples of how executable model and rule units can be mixed to this purpose.

    Drools Canonical Model – Pure Java Rules

    Rule engines, like Drools, typically  make use of a custom languages to define a set of rules. For example, he Drools compiler translates a drl file to an internal representation (the KiePackages) that is subsequently used to generate the ReteOO/Phreak network that will perform the rules evaluation.

    This internal representation was never really intended to be generated or consumed by end users. This complication makes it difficult to write rules programmatically and the suggestion is instead to generate text rules at the DRL level.  This means that drl itself is currently the only practical formal notation to define a set of rules in Drools.

    Drools internals were developed with several assumptions at the time, that are no longer true or desirable. Prior to Java 8, perm gen was a concern, so various solutions were utilized to address this – such as MVEL for reflective based evaluation. Java 8 now puts code on the heap, so this is no longer necessary.  A the engine level it also inspected and produced indexes, which tied it to the expressions produced by DRL – this makes polyglot impractical. Lastly it liberally uses classloaders and reflection, which makes it difficult to transpiler for execution on different environments.

    An engine independent rule model

    To overcome this limitation and offer the possibility of programmatically define a set of rule in pure Java we developed a model aimed to provide a canonical representation of a rule set and a fluent DSL to conveniently create an instance of this model. The model itself is totally independent from Drools and could in theory be re-used by other engines, It also introduces layers that fully separates the engine from having to be aware of any language. For example it will not inspect and generate indexes, instead it expects to be provided those indexes, from the layers above. Another advantage is it now means Drools has a developer friendly view of what it’s executing, as it’s all just pure low-level pojo rules.

    This model, other than giving to all Java developers a clean way to write rules in plain Java, will also enable our team to experiment with new features faster, freeing us from the burden of also implementing the corresponding parser and compiler parts that integrate the new feature with the drl notation.
    Let’s see a practical example of the model of a rule defined using the before mentioned DSL:

     
    Rule rule = rule( "Persons older than Mark" )
        .view(
            expr("exprA", markV, p -> p.getName().equals("Mark"))
                .indexedBy( String.class, ConstraintType.EQUAL, Person::getName, "Mark" )
                .reactOn( "name", "age" ),
            expr("exprB", olderV, p -> !p.getName().equals("Mark"))
                .indexedBy( String.class, ConstraintType.NOT_EQUAL, Person::getName, "Mark" )
                .reactOn( "name" ),
            expr("exprC", olderV, markV, (p1, p2) -> p1.getAge() > p2.getAge())
                .indexedBy( int.class, ConstraintType.GREATER_THAN, Person::getAge, Person::getAge )
                .reactOn( "age" )
        )
        .then(on(olderV, markV)
             .execute((p1, p2) -> System.out.println( p1.getName() + " is older than " + p2.getName())));

    This is the equivalent of the following rule expressed in drl:

     
    rule "Persons older than Mark" when
        $p1 : Person(name == "Mark")
        $p2 : Person(name != "Mark", age > $p1.age)
    then
        System.out.println($p2.getName() + " is older than " + $p1.getName());
    end

    It is evident that the DSL version is much more verbose and requires to specify many more details that conversely are inferred by the drools compiler when it parses the rule written in drl.
    As anticipated this has been done on purpose because the model has to explicitly contain all the information required to generate the section of ReteOO/Phreak network intended to evaluate that rule, without the need of performing any bytecode inspection or using any other complex, brittle and non-portable introspection technique. In those simple examples the index contains the same logic as the expr, as per DRL expressions can contain more than just the index. The index would be inferred and implicitly added by the upper language layers.
    To clarify this aspect let’s analyze a single LHS constraint in a bit more detail:

    expr("exprA",                                                                 [1] 
         markV,                                                                   [2]
         p -> p.getName().equals("Mark") )                                        [3] 
        .indexedBy( String.class, ConstraintType.EQUAL, Person::getName, "Mark" ) [4]
        .reactOn( "name", "age" )                                                 [5]

    In this statement you can notice the following parts
    [1] This is a label for the constraint used to determine its identity. Two identical constraint must have the same label and two different ones must have different labels in order to let the engine properly implement the node sharing where possible. This label can be optionally omitted and in this case it will be generated from an automatic introspection of the bytecode of the lambda expression implementing the constraint. However, as anticipated, it’s preferable to avoid any introspection mechanism and then to explicitly provide a constraint label whenever is possible.
    [2] This is the Variable defined before creating the rule and used to bind an actual fact with the formal parameter of the lambda expression used to evaluate a condition on it. It is the equivalent of the variable declaration in rule written with the drl notation.
    [3] The lambda expression performing the constraint evaluation.
    [4] The specification of the type of this constraint and how it has to be indexed by the engine.
    [5] The name of the properties of the Person object for which this constraint has to be reactive.

    Building and executing the model

    You can programmatically add this and other rules of your rule base to a model:

    Model model = new ModelImpl().addRule( rule );

    Once you have this model, which again is totally independent from Drools algorithms and data structures, you can use a second project, this time dependent both on Drools and on the model itself, to create a KieBase out of it.

    KieBase kieBase = KieBaseBuilder.createKieBaseFromModel( model );

    What this builder internally does is recreating the KiePackages out of the model and then building them using the existing drools compiler. The resulting KieBase is identical to the one you may obtain by compiling the corresponding drl and then you can use it exactly in the same way, creating a KieSession out of it and populating it with the facts of your domain. Here you can find more test cases showing the Drools features currently supported by the model and the DSL constructs allowing to use them, while here you can find a more complete example.

    Embedding the executable model inside the kjar

    At the moment a kjar contains some pregenerated classes implementing the constraints and the consequences. However all of the drl files need to be parsed and compiled from scratch, making limited savings on building it from source only.The executable model will be also useful to speed this process up. Embedding the classes implementing the model of the rule base inside the kjar, makes possible to quickly recreate the KiePackages, instead of having to restart the whole compilation process from the drl files. A proof concept of how this could work is available here.

    DRL compiler to Executable Model

    We are working on a new compiler that will take existing DRL and directly output the executable model, which is stored in the kjar. This will result in much faster loading and building times. We are also looking into other ways to speed this process up, by pre-caching more information in the kjar, which can be determined during the initial kjar build.

    Pojo, Polyglot and DRLX Rules

    The executable model is low level and because you have to provide all the information it needs, this makes it a little verbose. This is done by design, to support innovation in the language level. While it is technically still pojo-rules, it is not desirable for everyday use. In the near future we will work on a less verbose pojo rules layer, that will use an annotation processor to inject things like indexes and reactOn. We also hope that it will result in several rule languages, not just one – scala rules, closure rules, mini-dsl rules etc. Nor is it necessary for a language to expose all of the engine capabilities, people can write mini-dsls exposing the subset.

    Finally we are also working on a next generation DRL language (DRLX), that will be a superset of Java. This is still in the design phases and will not be available for some time, but we will publish some of the proposals for this, once an early draft spec is ready.

    Using a rective stream as a data source for Drools

    A few months ago we started redesigning the Drools lowest level executable model and making it accessible to end user with a Java 8 API. To demonstrate the flexibility of this approach I tried to integrate it with a reactive stream and in particular to use this stream as a data source for Drools.

    To show how this works I created a simple temperature server that provides a RxJava Observable emitting every second the temperature for a given town and terminates after 5 seconds. There is also a second factory method that allows to merge more of these Observables in order to have a single Observable that emits the temperature for more than one town at the same time.

    public class TempServer {
        public static Observable<TempInfo> getFeed(String town) {
            return Observable.create(subscriber ->
                                             Observable.interval(1, TimeUnit.SECONDS)
                                                       .subscribe(i -> {
                                                           if (i > 5) subscriber.onCompleted();
                                                           try {
                                                               subscriber.onNext(TempInfo.fetch(town));
                                                           } catch (Exception e) {
                                                               subscriber.onError(e);
                                                           }
                                                       }));
        }

        public static Observable<TempInfo> getFeeds(String... towns) {
            return Observable.merge(Arrays.stream(towns)
                                          .map(TempServer::getFeed)
                                          .collect(toList()));
        }
    }

    where the TempInfo.fetch method just returns a random temperature between -20 and 50 degrees

    public TempInfo(String town, int temp) {
        this.town = town;
        this.temp = temp;
    }

    public static TempInfo fetch(String town) {
        return new TempInfo(town, random.nextInt(70) - 20);
    }

    Using an improved version of the Java 8 DSL presented in the former article I defined the following 2 rules:

    Variable<TempInfo> temp = any( TempInfo.class );
    Variable<Person> person = any( Person.class );

    Rule r1 = rule("low temp")
            .view(
                    subscribe(temp, "tempFeed"),
                    expr(temp, t -> t.getTemp() < 0),
                    input(person, "persons"),
                    expr(person, temp, (p, t) -> p.getTown().equals(t.getTown()))
                 )
            .then(on(person, temp)
                          .execute((p, t) -> System.out.println(p.getName() + " is freezing in " + p.getTown() + " - temp is " + t.getTemp())));

    Rule r2 = rule("high temp")
            .view(
                    subscribe(temp, "tempFeed"),
                    expr(temp, t -> t.getTemp() > 30),
                    input(person, "persons"),
                    expr(person, temp, (p, t) -> p.getTown().equals(t.getTown()))
                 )
            .then(on(person, temp)
                          .execute((p, t) -> System.out.println(p.getName() + " is sweating in " + p.getTown() + " - temp is " + t.getTemp())));

    Here I’m using 2 different kinds of data sources: a passive one that can be considered a mere store of facts:

    DataStore persons = storeOf(new Person("Mark", 37, "London"),
                                new Person("Edson", 35, "Toronto"),
                                new Person("Mario", 40, "Milano"));

    that can be bound to a specific Drools KieSession with

    bindDataSource(ksession, "persons", persons);

    and a reactive one taken from the TempServer implemented above

    Observable<TempInfo> tempFeed = TempServer.getFeeds( "Milano", "London", "Toronto" );

    that can also be bound to the same KieSession in a similar way

    bindRxObservable( ksession, "tempFeed", tempFeed );

    Having done this you can fire those 2 rules and obtain an output like the following:

    Mark is freezing in London - temp is -9
    Edson is sweating in Toronto - temp is 42
    Mario is sweating in Milano - temp is 42
    Mario is sweating in Milano - temp is 49
    Mark is freezing in London - temp is -17
    Edson is sweating in Toronto - temp is 40
    Edson is sweating in Toronto - temp is 47
    Mario is freezing in Milano - temp is -14
    Mark is freezing in London - temp is -8
    Mark is freezing in London - temp is -17

    The complete test case to run this example is available here.

    Drools Executable Model (Rules in pure Java)

    The Executable Model is a re-design of the Drools lowest level model handled by the engine. In the current series (up to 6.x) the executable model has grown organically over the last 8 years, and was never really intended to be targeted by end users. Those wishing to programmatically write rules were advised to do it via code generation and target drl; which was no ideal. There was never any drive to make this more accessible to end users, because extensive use of anonymous classes in Java was unwieldy. With Java 8 and Lambda’s this changes, and the opportunity to make a more compelling model that is accessible to end users becomes possible.

    This new model is generated during the compilation process of higher level languages, but can also be used on its own. The goal is for this Executable Model to be self contained and avoid the need for any further byte code munging (analysis, transformation or generation); From this model’s perspective, everything is provided either by the code or by higher level language layers. For example indexes etc must be provided by arguments, which the higher level language generates through analysis, when it targets the Executable model.
       
    It is designed to map well to a Fluent level builders, leveraging Java 8’s lambdas. This will make it more appealing to java developers, and language developers. Also this will allow low level engine feature design and testing, independent of any language. Which means we can innovate at an engine level, without having to worry about the language layer.
       
    The Executable Model should be generic enough to map into multiple domains. It will be a low level dataflow model in which you can address functional reactive programming models, but still usable to build a rule based system out of it too.

    The following example provides a first view of the fluent DSL used to build the executable model

             
    DataSource persons = sourceOf(new Person("Mark", 37),
                                  new Person("Edson", 35),
                                  new Person("Mario", 40));
                         
    Variable<Person> markV = bind(typeOf(Person.class));
    
    Rule rule = rule("Print age of persons named Mark")
            .view(
                input(markV, () -> persons),
                expr(markV, person -> person.getName().equals("Mark"))
            )
            .then(
                on(markV).execute(mark -> System.out.println(mark.getAge())
            )
    );
    

    The previous code defines a DataSource containing a few person instances and declares the Variable markV of type Person. The rule itself contains the usual two parts: the LHS is defined by the set of inputs and expressions passed to the view() method, while the RHS is the action defined by the lambda expression passed to the then() method.

    Analyzing the LHS in more detail, the statement

             
    input(markV, () -> persons)
    

    binds the objects from the persons DataSource to the markV variable, pattern matching by the object class. In this sense the DataSource can be thought as the equivalent of a Drools entry-point.

    Conversely the expression

             
    expr(markV, person -> person.getName().equals("Mark"))
    

    uses a Predicate to define a condition that the object bound to the markV Variable has to satisfy in order to be successfully matched by the engine. Note that, as anticipated, the evaluation of the pattern matching is not performed by a constraint generated as a result of any sort of analysis or compilation process, but it’s merely executed by applying the lambda expression implementing the predicate ( in this case, person -> person.getName().equals(“Mark”) ) to the object to be matched. In other terms the former DSL produces the executable model of a rule that is equivalent to the one resulting from the parsing of the following drl.

             
    rule "Print age of persons named Mark"
    when
        markV : Person( name == "Mark" ) from entry-point "persons"
    then
        System.out.println(markV.getAge());
    end
    

    It is also under development a rete builder that can be fed with the rules defined with this DSL. In particular it is possible to add these rules to a CanonicalKieBase and then to create KieSessions from it as for any other normal KieBase.

             
    CanonicalKieBase kieBase = new CanonicalKieBase();
    kieBase.addRules(rule);
    
    KieSession ksession = kieBase.newKieSession();
    ksession.fireAllRules();
    

    Of course the DSL also allows to define more complex conditions like joins:

             
    Variable<Person> markV = bind(typeOf(Person.class));
    Variable<Person> olderV = bind(typeOf(Person.class));
    
    Rule rule = rule("Find persons older than Mark")
            .view(
                input(markV, () -> persons),
                input(olderV, () -> persons),
                expr(markV, mark -> mark.getName().equals("Mark")),
                expr(olderV, markV, (older, mark) -> older.getAge() > mark.getAge())
            )
            .then( 
                on(olderV, markV)
                    .execute((p1, p2) -> System.out.println(p1.getName() + " is older than " + p2.getName())
            )
    );
    

    or existential patterns:

     
    Variable<Person> oldestV = bind(typeOf(Person.class));
    Variable<Person> otherV = bind(typeOf(Person.class));
    
    Rule rule = rule("Find oldest person")
            .view(
                input(oldestV, () -> persons),
                input(otherV, () -> persons),
                not(otherV, oldestV, (p1, p2) -> p1.getAge() > p2.getAge())
            )
            .then( 
                on(oldestV)
                    .execute(p -> System.out.println("Oldest person is " + p.getName())
            )
    );
    

    Here the not() stands for the negation of any expression, so the form used above is actually only a shortcut for

     
    not( expr( otherV, oldestV, (p1, p2) -> p1.getAge() > p2.getAge() ) )
    

    Also accumulate is already supported in the following form:

     
    Variable<Person> person = bind(typeOf(Person.class));
    Variable<Integer> resultSum = bind(typeOf(Integer.class));
    Variable<Double> resultAvg = bind(typeOf(Double.class));
    
    Rule rule = rule("Calculate sum and avg of all persons having a name starting with M")
            .view(
                input(person, () -> persons),
                accumulate(expr(person, p -> p.getName().startsWith("M")),
                           sum(Person::getAge).as(resultSum),
                           avg(Person::getAge).as(resultAvg))
            )
            .then(
                on(resultSum, resultAvg)
                    .execute((sum, avg) -> result.value = "total = " + sum + "; average = " + avg)
    );
    

    To provide one last more complete use case, the executable model of the classical fire and alarm example can be defined with this DSL as it follows.

     
    Variable<Room> room = any(Room.class);
    Variable<Fire> fire = any(Fire.class);
    Variable<Sprinkler> sprinkler = any(Sprinkler.class);
    Variable<Alarm> alarm = any(Alarm.class);
    
    Rule r1 = rule("When there is a fire turn on the sprinkler")
            .view(
                input(fire),
                input(sprinkler),
                expr(sprinkler, s -> !s.isOn()),
                expr(sprinkler, fire, (s, f) -> s.getRoom().equals(f.getRoom()))
            )
            .then(
                on(sprinkler)
                    .execute(s -> {
                        System.out.println("Turn on the sprinkler for room " + s.getRoom().getName());
                        s.setOn(true);
                    })
                    .update(sprinkler, "on")
    );
    
    Rule r2 = rule("When the fire is gone turn off the sprinkler")
            .view(
                input(sprinkler),
                expr(sprinkler, Sprinkler::isOn),
                input(fire),
                not(fire, sprinkler, (f, s) -> f.getRoom().equals(s.getRoom()))
            )
            .then(
                on(sprinkler)
                    .execute(s -> {
                        System.out.println("Turn off the sprinkler for room " + s.getRoom().getName());
                        s.setOn(false);
                    })
                    .update(sprinkler, "on")
    );
    
    Rule r3 = rule("Raise the alarm when we have one or more fires")
            .view(
                input(fire),
                exists(fire)
            )
            .then(
                execute(() -> System.out.println("Raise the alarm"))
                    .insert(() -> new Alarm())
    );
    
    Rule r4 = rule("Lower the alarm when all the fires have gone")
            .view(
                input(fire),
                not(fire),
                input(alarm)
            )
            .then(
                execute(() -> System.out.println("Lower the alarm"))
                    .delete(alarm)
    );
    
    Rule r5 = rule("Status output when things are ok")
            .view(
                input(alarm),
                not(alarm),
                input(sprinkler),
                not(sprinkler, Sprinkler::isOn)
            )
            .then(
                execute(() -> System.out.println("Everything is ok"))
    );
    
    CanonicalKieBase kieBase = new CanonicalKieBase();
    kieBase.addRules(r1, r2, r3, r4, r5);
    
    KieSession ksession = kieBase.newKieSession();
    
    // phase 1
    Room room1 = new Room("Room 1");
    ksession.insert(room1);
    FactHandle fireFact1 = ksession.insert(new Fire(room1));
    ksession.fireAllRules();
    
    // phase 2
    Sprinkler sprinkler1 = new Sprinkler(room1);
    ksession.insert(sprinkler1);
    ksession.fireAllRules();
    
    assertTrue(sprinkler1.isOn());
    
    // phase 3
    ksession.delete(fireFact1);
    ksession.fireAllRules();
    

    In this example it’s possible to note a few more things:

    • Some repetitions are necessary to bind the parameters of an expression to the formal parameters of the lambda expression evaluating it. Hopefully it will be possible to overcome this issue using the -parameters compilation argument when this JDK bug will be resolved.
    • any(Room.class) is a shortcut for bind(typeOf(Room.class))
    • The inputs don’t declare a DataSource. This is a shortcut to state that those objects come from a default empty DataSource (corresponding to the Drools default entry-point). In fact in this example the facts are programmatically inserted into the KieSession.
    • Using an input without providing any expression for that input is actually a shortcut for input(alarm), expr(alarm, a -> true)
    • In the same way an existential pattern without any condition like not(fire) is another shortcut for not( expr( fire, f -> true ) )
    • Java 8 syntax also allows to define a predicate as a method reference accessing a boolean property of a fact like in expr(sprinkler, Sprinkler::isOn)
    • The RHS, together with the block of code to be executed, also provides a fluent interface to define the working memory actions (inserts/updates/deletes) that have to be performed when the rule is fired. In particular the update also gets a varargs of Strings reporting the name of the properties changed in the updated fact like in update(sprinkler, “on”). Once again this information has to be explicitly provided because the executable model has to be created without the need of any code analysis.

    (Conditional) Named consequences in Drools 5.5

    Until now Drools rules have been always expressed in the form:

    rule "name"
    when
    LHS (conditional element)
    then
    RHS (consequence)
    end

    Sometimes this could be somewhat limiting and leads to verbose and difficult to be maintained repetitions like in the following example:

    rule "Give 10% discount to customers older than 60"
    when
    $customer : Customer( age > 60 )
    then
    modify($customer) { setDiscount( 0.1 ) };
    end

    rule "Give free parking to customers older than 60"
    when
    $customer : Customer( age > 60 )
    $car : Car ( owner == $customer )
    then
    modify($car) { setFreeParking( true ) };
    end

    It is already possible to partially overcome this problem by making the second rule extending the first one like in:

    rule "Give 10% discount to customers older than 60"
    when
    $customer : Customer( age > 60 )
    then
    modify($customer) { setDiscount( 0.1 ) };
    end

    rule "Give free parking to customers older than 60"
    extends "Give 10% discount to customers older than 60"
    when
    $car : Car ( owner == $customer )
    then
    modify($car) { setFreeParking( true ) };
    end

    Anyway, starting from Drools 5.5, it is possible to define more labelled consequences other than the default one in a single rule, so, for example, the 2 former rules can be compacted in only one like it follows:

    rule "Give 10% discount and free parking to customers older than 60"
    when
    $customer : Customer( age > 60 )
    do[giveDiscount]
    $car : Car ( owner == $customer )
    then
    modify($car) { setFreeParking( true ) };
    then[giveDiscount]
    modify($customer) { setDiscount( 0.1 ) };
    end

    This last rule has 2 consequences, the usual default one, plus another one named “giveDiscount” that is activated, using the keyword do, as soon as a customer older than 60 is found in the knowledge base, regardless of the fact that he owns a car or not. The activation of a named consequence can be also guarded by an additional condition like in this further example:

    rule "Give free parking to customers older than 60 and 10% discount to golden ones among them"
    when
    $customer : Customer( age > 60 )
    if ( type == "Golden" ) do[giveDiscount]
    $car : Car ( owner == $customer )
    then
    modify($car) { setFreeParking( true ) };
    then[giveDiscount]
    modify($customer) { setDiscount( 0.1 ) };
    end

    The condition in the if statement is always evaluated on the pattern immediately preceding it. In the end this last, a bit more complicated, example shows how it is possible to switch over different conditions using a nested if/else statement:

    rule "Give free parking and 10% discount to over 60 Golden customer and 5% to Silver ones"
    when
    $customer : Customer( age > 60 )
    if ( type == "Golden" ) do[giveDiscount10]
    else if ( type == "Silver" ) break[giveDiscount5]
    $car : Car ( owner == $customer )
    then
    modify($car) { setFreeParking( true ) };
    then[giveDiscount10]
    modify($customer) { setDiscount( 0.1 ) };
    then[giveDiscount5]
    modify($customer) { setDiscount( 0.05 ) };
    end

    Here I wanted to give a 10% discount AND a free parking to Golden customers over 60, but only a 5% discount (without free parking) to the Silver ones. I achieved this result by activating the consequence named “giveDiscount5” using the keyword break instead of do. In fact do just schedules a consequence in the agenda, allowing the remaining part of the LHS to continue of being evaluated as per normal, while break also blocks any further pattern matching evaluation. Note, of course, that the activation of a named consequence not guarded by any condition with break doesn’t make sense (and generates a compile time error) since otherwise the LHS part following it would be never reachable.

    — updated —
    To clarify some of comments. Here is an if..do rule, from above

    rule "Give free parking to customers older than 60 and 10% discount to golden ones among them"
    when
    $customer : Customer( age > 60 )
    if ( type == "Golden" ) do[giveDiscount]
    $car : Car ( owner == $customer )
    then
    modify($car) { setFreeParking( true ) };
    then[giveDiscount]
    modify($customer) { setDiscount( 0.1 ) };
    end

    That rule is the equivalent of the two single rules:

    rule "Give free parking to customers older than 60 and 10% discount to golden ones among them"
    when
    $customer : Customer( age > 60 )
    $car : Car ( owner == $customer )
    then
    modify($car) { setFreeParking( true ) };
    end

    rule "Give free parking to customers older than 60 and 10% discount to golden ones among them - 1"
    when
    $customer : Customer( age > 60 )
    eval ( $customer.type == "Golden" )
    then
    modify($customer) { setDiscount( 0.1 ) };
    end

    The same rule but a ‘if..break’ instead:

    rule "Give free parking to customers older than 60 and 10% discount to golden ones among them - 2"
    when
    $customer : Customer( age > 60 )
    if ( type == "Golden" ) break[giveDiscount]
    $car : Car ( owner == $customer )
    then
    modify($car) { setFreeParking( true ) };
    then[giveDiscount]
    modify($customer) { setDiscount( 0.1 ) };
    end

    Notice the negation of the eval:

    rule "Give free parking to customers older than 60 and 10% discount to golden ones among them - 1"
    when
    $customer : Customer( age > 60 )
    eval ( ! ($customer.type == "Golden") )
    $car : Car ( owner == $customer )
    then
    modify($car) { setFreeParking( true ) };
    end

    rule "Give free parking to customers older than 60 and 10% discount to golden ones among them - 2"
    when
    $customer : Customer( age > 60 )
    eval ( $customer.type == "Golden" )
    then
    modify($customer) { setDiscount( 0.1 ) };
    end

    If we take the last, more complex rule:

    rule "Give free parking and 10% discount to over 60 Golden customer and 5% to Silver ones"
    when
    $customer : Customer( age > 60 )
    if ( type == "Golden" ) do[giveDiscount10]
    else if ( type == "Silver" ) break[giveDiscount5]
    $car : Car ( owner == $customer )
    then
    modify($car) { setFreeParking( true ) };
    then[giveDiscount10]
    modify($customer) { setDiscount( 0.1 ) };
    then[giveDiscount5]
    modify($customer) { setDiscount( 0.05 ) };
    end

    That translates into the following three rules. Notice for the free parking I explicitly add in all the negations that are implicit to the above rule.

    rule "Give free parking and 10% discount to over 60 Golden customer and 5% to Silver ones - 1"
    when
    $customer : Customer( age > 60 )
    eval( $customer.type == "Golden" )
    then
    modify($customer) { setDiscount( 0.1 ) };
    end

    rule "Give free parking and 10% discount to over 60 Golden customer and 5% to Silver ones - 2"
    when
    $customer : Customer( age > 60 )
    eval( !( $customer.type == "Golden" ) && $customer.type == "Silver" )
    then
    modify($customer) { setDiscount( 0.05 ) };
    end

    rule "Give free parking and 10% discount to over 60 Golden customer and 5% to Silver ones - 3"
    when
    $customer : Customer( age > 60 )
    eval( ( $customer.type == "Golden" ) ||
    ( !( $customer.type == "Golden" ) && !( $customer.type == "Silver" ) ) ) )
    $car : Car ( owner == $customer )
    then
    modify($car) { setFreeParking( true ) };
    end

    We have further work coming down the line, that will allow nested patterns inside of the branch’s. You can see an early draft proposal of this here: https://community.jboss.org/wiki/BranchCEs

    Small efforts, big improvements

    Some days ago, following some suggestions of Mark Proctor, I spent just a few hours trying to reduce both the memory footprint and the time requested to create an instance of the WorkingMemory, one of the most used core class of Drools. What I basically did was to lazy initialize all the non-strictly necessary data structures of that class, moving their creation away from the constructor, and rewrite a private method, also invoked during the initialization phase, that used some of those data-structure in a sub-optimal way.

    Now I just had time to measure the actual improvements brought by my rework and I must say I was quite positively surprised of the results, especially if compared with the amount of time I spent to implement them. In particular I just tried to create a StatefulSession (that of course uses a WorkingMemory internally) starting from a KnowledgeBase with only one simple rule.

    What I found is that my enhancements reduced the memory occupation of that StatefulSession from the initial 11,336 bytes to only 8,610. Even more impressive, the number of instances of StatefulSession I could create in a second, on my machine, increased from the initial 4,668 to an amazing 12,304.

    I hope this demonstrates that, even when it seems unlikely, there could be almost always room for important improvements and, at the same time, that not all those improvements comes with a cost, in terms of effort, related with the real benefits they can bring.