Chapter 11. Objects and Interfaces
11.1. Globals Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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
Commandto set a global which is then passed to theCommandExecutor.
11.4. Session Scoped Global Example Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
The
KnowlegeRuntimeEventManager interface is implemented by the KnowledgeRuntime which provides two interfaces, WorkingMemoryEventManager and ProcessEventManager.
11.11. The WorkingMemoryEventManager Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
This code lets you print all Working Memory events by adding a listener:
ksession.addEventListener( new DebugWorkingMemoryEventListener() );
11.14. KnowlegeRuntimeEvents Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
The events currently supported are:
- ActivationCreatedEvent
- ActivationCancelledEvent
- BeforeActivationFiredEvent
- AfterActivationFiredEvent
- AgendaGroupPushedEvent
- AgendaGroupPoppedEvent
- ObjectInsertEvent
- ObjectRetractedEvent
- ObjectUpdatedEvent
- ProcessCompletedEvent
- ProcessNodeLeftEvent
- ProcessNodeTriggeredEvent
- ProcessStartEvent
11.16. The KnowledgeRuntimeLogger Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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 Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
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" );