Chapter 11. Objects and Interfaces

11.1. Globals

Globals are named objects that are made visible to the rule engine, but unlike facts, changes in the object backing a global do not trigger reevaluation of rules. 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 else your changes will not have any effect on the behavior of your rules.

11.2. Working With Globals

Procedure 11.1. Task

  1. To start implementing globals into the Working Memory, declare a global in a rules file and back it up with a Java object:
    global java.util.List list
  2. With the Knowledge Base now aware of the global identifier and its type, you can call ksession.setGlobal() with the global's name and an object (for any session) to associate the object with the global:
    List list = new ArrayList();
    ksession.setGlobal("list", list);

    Important

    Failure to declare the global type and identifier in DRL code will result in an exception being thrown from this call.
  3. Set the global before it is used in the evaluation of a rule. Failure to do so results in a NullPointerException.

11.3. Resolving Globals

Globals can be resolved in three ways:
getGlobals()
The Stateless Knowledge Session 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.
Delegates
Using a delegate is another way of providing 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. If an identifier cannot be found in this internal collection, the delegate global (if any) will be used.
Execution
Execution scoped globals use a Command to set a global which is then passed to the CommandExecutor.

11.4. Session Scoped Global Example

This is what a session scoped Global looks like:
StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
// 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 );

11.5. StatefulRuleSessions

The StatefulRuleSession property is inherited by the StatefulKnowledgeSession and provides the rule-related methods that are relevant from outside of the engine.

11.6. AgendaFilter Objects

AgendaFilter objects are optional implementations of the filter interface which are used to allow or deny the firing of an activation. What is filtered depends on the implementation.

11.7. Using the AgendaFilter

Procedure 11.2. Task

  • To use a filter specify it while calling fireAllRules(). The following example permits only rules ending in the string "Test". All others will be filtered out:
    ksession.fireAllRules( new RuleNameEndsWithAgendaFilter( "Test" ) );

11.8. Rule Engine Phases

The engine cycles repeatedly through two phases:
Working Memory Actions
This is where most of the work takes place, either in the Consequence (the RHS itself) or the main Java application process. Once the Consequence has finished or the main Java application process calls fireAllRules() the engine switches to the Agenda Evaluation phase.
Agenda Evaluation
This attempts to select a rule to fire. If no rule is found it exits. Otherwise it fires the found rule, switching the phase back to Working Memory Actions.
The process repeats until the agenda is clear, in which case control returns to the calling application. When Working Memory Actions are taking place, no rules are being fired.

11.9. The 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).

11.10. The KnowlegeRuntimeEventManager

The KnowlegeRuntimeEventManager interface is implemented by the KnowledgeRuntime which provides two interfaces, WorkingMemoryEventManager and ProcessEventManager.

11.11. The WorkingMemoryEventManager

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

11.12. Adding an AgendaEventListener

The following code snippet shows how a simple agenda listener is declared and attached to a session. It will print activations after they have fired:
ksession.addEventListener( new DefaultAgendaEventListener() {
   public void afterActivationFired(AfterActivationFiredEvent event) {
       super.afterActivationFired( event );
       System.out.println( event );
   }
});

11.13. Printing Working Memory Events

This code lets you print all Working Memory events by adding a listener:
ksession.addEventListener( new DebugWorkingMemoryEventListener() );

11.14. KnowlegeRuntimeEvents

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

11.15. Supported Events for the KnowledgeRuntimeEvent Interface

The events currently supported are:
  • ActivationCreatedEvent
  • ActivationCancelledEvent
  • BeforeActivationFiredEvent
  • AfterActivationFiredEvent
  • AgendaGroupPushedEvent
  • AgendaGroupPoppedEvent
  • ObjectInsertEvent
  • ObjectRetractedEvent
  • ObjectUpdatedEvent
  • ProcessCompletedEvent
  • ProcessNodeLeftEvent
  • ProcessNodeTriggeredEvent
  • ProcessStartEvent

11.16. The KnowledgeRuntimeLogger

The KnowledgeRuntimeLogger uses the comprehensive event system in JBoss Rules 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.

11.17. Enabling a FileLogger

To enable a FileLogger to track your files, use this code:
KnowledgeRuntimeLogger logger =
  KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "logdir/mylogfile");
...
logger.close();

11.18. Using StatelessKnowledgeSession in JBoss Rules

The StatelessKnowledgeSession wraps the StatefulKnowledgeSession, 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 StatefulKnowledgeSession, 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.

11.19. Performing a StatelessKnowledgeSession Execution with a Collection

This the code for performing a StatelessKnowledgeSession execution with a collection:
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newFileSystemResource( fileName ), ResourceType.DRL );
if (kbuilder.hasErrors() ) {
    System.out.println( kbuilder.getErrors() );
} else {
    KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
    kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
    StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
    ksession.execute( collection );
}

11.20. Performing a StatelessKnowledgeSession Execution with the InsertElements Command

This is the code for performing a StatelessKnowledgeSession execution with the InsertElements Command:
ksession.execute( CommandFactory.newInsertElements( collection ) );

Note

To insert the collection and its individual elements, use CommandFactory.newInsert(collection).

11.21. The BatchExecutionHelper

Methods of the CommandFactory create the supported commands, all of which can be marshaled using XStream and the BatchExecutionHelper. BatchExecutionHelper provides details on the XML format as well as how to use JBoss Rules Pipeline to automate the marshaling of BatchExecution and ExecutionResults.

11.22. The CommandExecutor Interface

The CommandExecutor interface allows users to export data using "out" parameters. This means that inserted facts, globals and query results can all be returned using this interface.

11.23. Out Identifiers

This is an example of what out identifiers look like:
// 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" );
Red Hat logoGithubRedditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat Documentation

We help Red Hat users innovate and achieve their goals with our products and services with content they can trust.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

© 2024 Red Hat, Inc.