Red Hat Training
A Red Hat training course is available for JBoss Enterprise SOA Platform
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
- 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
- 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. - 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 theCommandExecutor
.
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" );