[JBoss JIRA] Created: (JBRULES-2457) Wrong evaluation of rules and PseudoClock NPE
by Vítor Moreira (JIRA)
Wrong evaluation of rules and PseudoClock NPE
---------------------------------------------
Key: JBRULES-2457
URL: https://jira.jboss.org/jira/browse/JBRULES-2457
Project: Drools
Issue Type: Bug
Security Level: Public (Everyone can see)
Affects Versions: 5.1.0.M1, 5.0.1.FINAL
Environment: Windows 7, Eclipse 3.4, Java 1.6.0_u18, JUnit 4
Reporter: Vítor Moreira
Assignee: Mark Proctor
I've got a DRL file, having the following rules:
- offline event for 3 minutes withou any online event meanwhile => send an offline notification
- online event after offline event (within 3 minute range) => send an online notification
I've also got an junit test:
- insert offline event
- pseudoclock advances 2m50s
- insert online event
- pseudoclock advances 15s
- check if there's any notification
And the result of the junit is:
1) NPE when clock advances 15s
java.lang.NullPointerException
at org.drools.util.LinkedList.remove(LinkedList.java:113)
at org.drools.common.Scheduler$DuractionJob.execute(Scheduler.java:71)
at org.drools.time.impl.PseudoClockScheduler$ScheduledJob.call(PseudoClockScheduler.java:219)
at org.drools.time.impl.PseudoClockScheduler.runCallBacks(PseudoClockScheduler.java:168)
at org.drools.time.impl.PseudoClockScheduler.advanceTime(PseudoClockScheduler.java:130)
2) When checking for a notification, it should have one online notification but has on offline notification
At the bottom of this issue, there are snippets of junit code and drools rule file.
Probably, the problem relies on Junit initialization code.
T.I.A.
-- DRL file (snippet) --
dialect "java"
declare Event
@role( event )
@expires ( 7d )
end
global ISnmpNotifier snmpNotifier;
/*************************/
/* OFFLINE FOR 3 MINUTES */
/*************************/
rule "bit\dom - events offline (device offline for 3 minutes)"
when
$offline : Event( freeField == "101", $offlineLane : lane ) from entry-point "incoming"
not ( $online : Event (freeField == "102", lane == $offlineLane, this after [0s,3m] $offline ) from entry-point "incoming" )
then
snmpNotifier.send( new Notification("101", "offline") );
end
rule "bit\dom - events online (device offline for 3 minutes)"
when
$offline: Event( freeField == "101", $lane : lane ) from entry-point "incoming"
$online : Event( freeField == "102", lane == $lane, this after [3m] $offline ) from entry-point "incoming"
then
snmpNotifier.send( new Notification("102", "online") );
end
-- DRL file (snippet) --
-- JUnit code (snippet) --
package pt.brisa.sam.agent.rules.bit_dom;
import java.util.concurrent.TimeUnit;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseConfiguration;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.conf.EventProcessingOption;
import org.drools.io.ResourceFactory;
import org.drools.runtime.KnowledgeSessionConfiguration;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.conf.ClockTypeOption;
import org.drools.runtime.rule.WorkingMemoryEntryPoint;
import org.drools.time.impl.PseudoClockScheduler;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class Jira_Drools {
// values used to create test
private String offlineEventCode = "101";
private String onlineEventCode = "102";
private String device = "device";
// drools specific vars
private WorkingMemoryEntryPoint workingMemoryEntryPoint;
private PseudoClockScheduler clock = null;
private StatefulKnowledgeSession kSession;
/**
* SnmpNotificationEventCase.getNumberOfNotificationsByExample(example)
* .getNumberOfNotificationsByExample => from the notification queue, returns the number of notifications matching the given example
*/
private SnmpNotificationEventCase snmpNotificationEventCase;
@Before
public void droolsSetup() {
KnowledgeBaseConfiguration baseConfig;
KnowledgeSessionConfiguration sessionConfig;
KnowledgeBase kBase;
KnowledgeBuilder kBuilder;
baseConfig = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
baseConfig.setOption( EventProcessingOption.STREAM ); // Use stream mode
kBuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kBuilder.add(ResourceFactory.newFileResource( "test.drl"), ResourceType.DRL);
kBase = KnowledgeBaseFactory.newKnowledgeBase(baseConfig);
kBase.addKnowledgePackages(kBuilder.getKnowledgePackages());
sessionConfig = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
sessionConfig.setOption( ClockTypeOption.get( "pseudo" ) );
kSession = kBase.newStatefulKnowledgeSession( sessionConfig, null );
kSession.setGlobal( "snmpNotifier", snmpNotificationEventCase );
workingMemoryEntryPoint = kSession.getWorkingMemoryEntryPoint("incoming");
clock = (PseudoClockScheduler) kSession.getSessionClock();
snmpNotificationEventCase = new SnmpNotificationEventCase();
}
/* offline online 3min */
/* -----|-------------------|------/----^----- */
/* check */
@Test
public void deviceOffline_onlineBefore3minutes_checkAfter3minutes() {
/* alocates OFFLINE and ONLINE events, EXAMPLE */
Event offlineEvent = new Event();
Event onlineEvent = new Event();
Notification example = new Notification();
/* configures the events */
offlineEvent.setFreeField( offlineEventCode );
offlineEvent.setEventType( (byte)5 );
offlineEvent.setEventCode( "0001000" + offlineEventCode );
offlineEvent.setFormattedMessage( "JUnit string test" );
offlineEvent.setLane( "102" );
onlineEvent.setFreeField( onlineEventCode );
onlineEvent.setEventType( (byte)3 );
onlineEvent.setEventCode( "0001000" + onlineEventCode );
onlineEvent.setFormattedMessage( "JUnit string test" );
onlineEvent.setLane( "102" );
/* insert offline event */
workingMemoryEntryPoint.insert( offlineEvent );
kSession.fireAllRules();
/* intermediary check - offline notification */
example.setRuleCode( "31" );
example.setEventCode( offlineEventCode );
Assert.assertTrue(
"(device "+device+")(ruleCode 31): There are OFFLINE notifications, when it shouldn't have",
snmpNotificationEventCase.getNumberOfNotificationsByExample(example) == 0 );
/* advances the clock */
clock.advanceTime( 2, TimeUnit.MINUTES );
clock.advanceTime( 50, TimeUnit.SECONDS );
/* intermediary check - offline notification */
example.setRuleCode( "31" );
example.setEventCode( offlineEventCode );
Assert.assertTrue(
"(device "+device+")(ruleCode 31): There are OFFLINE notifications, when it shouldn't have",
snmpNotificationEventCase.getNumberOfNotificationsByExample(example) == 0 );
/* insert online event */
workingMemoryEntryPoint.insert( onlineEvent );
kSession.fireAllRules();
/* intermediary check - offline notification */
example.setRuleCode( "31" );
example.setEventCode( offlineEventCode );
Assert.assertTrue(
"(device "+device+")(ruleCode 31): There are OFFLINE notifications, when it shouldn't have",
snmpNotificationEventCase.getNumberOfNotificationsByExample(example) == 0 );
/* intermediary check - online notification */
example.setRuleCode( "31" );
example.setEventCode( onlineEventCode );
Assert.assertTrue(
"(device "+device+")(ruleCode 31): There are ONLINE notifications, when it shouldn't have",
snmpNotificationEventCase.getNumberOfNotificationsByExample(example) == 0 );
/* advances the clock */
clock.advanceTime( 15, TimeUnit.SECONDS );
/* since there's an ONLINE before the 3 minute's limit, there shouldn't be any trap regarding "last offline 3 minutes ago" */
example.setRuleCode( "31" );
example.setEventCode( offlineEventCode );
Assert.assertTrue(
"(device "+device+")(ruleCode 31): There are OFFLINE notifications, when it shouldn't have",
snmpNotificationEventCase.getNumberOfNotificationsByExample(example) == 0 );
example.setRuleCode( "31" );
example.setEventCode( onlineEventCode );
Assert.assertTrue(
"(device "+device+")(ruleCode 31): There are ONLINE notifications, when it shouldn't have",
snmpNotificationEventCase.getNumberOfNotificationsByExample(example) == 1 );
}
}
-- JUnit code (snippet) --
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2673) There Should be a Relation Between the Fired Rule and the Node which Activates the Ruleflow-Group
by Anatoly Polinsky (JIRA)
There Should be a Relation Between the Fired Rule and the Node which Activates the Ruleflow-Group
-------------------------------------------------------------------------------------------------
Key: JBRULES-2673
URL: https://jira.jboss.org/browse/JBRULES-2673
Project: Drools
Issue Type: Bug
Security Level: Public (Everyone can see)
Affects Versions: 5.1.1.FINAL
Environment: N/A
Reporter: Anatoly Polinsky
Assignee: Mark Proctor
We asked for the following behavior to be implemented:
@Test(expected=NameOfOurLayerOtTopOfDroolsException.class)
public void shouldThrowNameOfOurLayerOtTopOfDroolsExceptionForAnyThrowableThrownWithinDroolsOnTheProcessStart() {
ksession.startProcess("com.jpmc...process-throws-throwable");
}
@Test(expected=NameOfOurLayerOtTopOfDroolsException.class)
public void shouldThrowNameOfOurLayerOtTopOfDroolsExceptionForAnyThrowableThrownWithinDroolsOnTheProcessResume() {
ksession.getWorkItemManager().completeWorkItem( id, null );
}
And Plugtree was prompt to create it for us: http://anonsvn.jboss.org/repos/labs/labs/jbossrules/branches/5_1_20100802...
The only roadblock here, to fulfill our original request, is when Throwable is thrown from within a "ruleflow-group" ( from within rules that are embedded into / invoked from a workflow ), in which case Throwable cannot be caught by the above mechanism due to the fact that:
"At the moment Drools doesn't keep any relation between the fired rule and the node which activates the ruleflow-group, thus if an activated rule blows up there is no way to know which node has made focus on its group"
Since Drools is moving towards having everything under "a single roof/parent of Knowledge", Process and Rule children should be rather siblings than strangers, hence should know a little more about each other.
/Anatoly
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2650) Stable API should provide Agenda.getActivations()
by Wolfgang Laun (JIRA)
Stable API should provide Agenda.getActivations()
-------------------------------------------------
Key: JBRULES-2650
URL: https://jira.jboss.org/browse/JBRULES-2650
Project: Drools
Issue Type: Feature Request
Security Level: Public (Everyone can see)
Components: drools-api
Affects Versions: 5.1.0.FINAL
Reporter: Wolfgang Laun
Assignee: Mark Proctor
Fix For: 5.1.1.FINAL
The stable API lets you retrieve Agenda from WorkingMemory, and there is an IF for Activation. There should be a
List<Activation> getActivations
in the "stable" Agenda.
This would be highly useful for writing supportive code for inspecting the engine's state at critical points. (I don't see that restricting Agenda views to specific "groups" would be a benefit for such tasks.)
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2691) Accumulated Code Clean-Up Issues
by Wolfgang Laun (JIRA)
Accumulated Code Clean-Up Issues
--------------------------------
Key: JBRULES-2691
URL: https://jira.jboss.org/browse/JBRULES-2691
Project: Drools
Issue Type: Bug
Security Level: Public (Everyone can see)
Components: All
Reporter: Wolfgang Laun
Assignee: Mark Proctor
This issue is meant to be a portmanteau for all relics resulting from refactorings, modifactions, additions and deletions - in short, the flotsam and jetsam of ongoing software maintenance.
(.) There are two eponymous classes:
org.drools.base.DefaultConsequenceExceptionHandler
org.drools.runtime.rule.impl.DefaultConsequenceExceptionHandler
and, thrown from these:
org.drools.spi.ConsequenceException
org.drools.runtime.rule.ConsequenceException
Mark: "I believe it's historical,... drools-api has been there long enough that we can start to clean all this up now."
(.) Problem reported with
ksession.fireAllRules(new RuleNameEndsWithAgendaFilter("test"));
Thomas Swindells: Looks like [...] that there are two agenda filter classes:
org.drools.runtime.rule.AgendaFilter and
org.drools.spi.AgendaFilter.
The first one, odrr.AgendaFilter is what is required by the StatefulKnowledgeSession, this then wraps it in a class to convert it to an ods.AgendaFilter which is what the internal classes use. RuleNameEndsWithAgendaFilter seems to implement ods.AgendaFilter and not odrr.AgendaFilter which is what I'd expect - this is possibly a bug.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2554) Adding a StatefulKnowledgeSessionAware Interface
by Anatoly Polinsky (JIRA)
Adding a StatefulKnowledgeSessionAware Interface
------------------------------------------------
Key: JBRULES-2554
URL: https://jira.jboss.org/browse/JBRULES-2554
Project: Drools
Issue Type: Feature Request
Security Level: Public (Everyone can see)
Components: drools-api
Affects Versions: 5.1.0.M2
Environment: N/A
Reporter: Anatoly Polinsky
Assignee: Mark Proctor
Priority: Minor
Interface to be implemented by any object that wishes to be notified of the {@link org.drools.runtime.StatefulKnowledgeSession} that it runs in.
Implementing this interface makes sense for example when an object requires access to session artifacts/details such as rule facts, sessionID, etc.
This interface can be implemented by a custom {@link org.drools.process.instance.WorkItemHandler} in case, for example, it needs to access a session to insert / retract some facts before proceeding further to the process node that fires rules ( groups, agendas, etc.. ).
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2621) NPE due to activation.getDeclarationValue( declId )
by Wolfgang Laun (JIRA)
NPE due to activation.getDeclarationValue( declId )
---------------------------------------------------
Key: JBRULES-2621
URL: https://jira.jboss.org/browse/JBRULES-2621
Project: Drools
Issue Type: Bug
Security Level: Public (Everyone can see)
Components: drools-api
Affects Versions: 5.1.0.FINAL
Reporter: Wolfgang Laun
Assignee: Mark Proctor
Fix For: 5.1.1.FINAL
Trying to access the declarations and their values of an activation, as used during ActivationEvent logging:
List<String> declIds = );
for( String declId: activation.getDeclarationIDs( ){
Object declVal = activation.getDeclarationValue( declId );
// ...
}
If, however, a fact is retracted, this code, when executed for an AfterActivationFiredEvent, throws a NPE when declId is a binding for a component of the retracted fact.
The optimum solution would be to not get such useless bindings in the List<String> returned by getDeclarationIDs() which is in AgendaItem.java. I have added the if-statement. The following code is untested:
public List<String> getDeclarationIDs() {
Declaration[] declArray = this.getRule().getDeclarations();
List<String> declarations = new ArrayList<String>();
for( Declaration decl : declArray ) {
// return only "sound" declaration IDs
if( this.tuple.get( decl ).getObject() != null ){
declarations.add( decl.getIdentifier() );
}
}
return Collections.unmodifiableList( declarations );
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2619) Extend API of IF Rule: no access to interesting attributes
by Wolfgang Laun (JIRA)
Extend API of IF Rule: no access to interesting attributes
--------------------------------------------------------------
Key: JBRULES-2619
URL: https://jira.jboss.org/browse/JBRULES-2619
Project: Drools
Issue Type: Feature Request
Security Level: Public (Everyone can see)
Components: drools-api
Affects Versions: 5.1.0.FINAL
Reporter: Wolfgang Laun
Assignee: Mark Proctor
Fix For: 5.2.0.M1
Whereas org.drools.rule.Rule contains a wealth of interesting fields, the stable API org.drools.definition.rule.Rule restricts us to
getName() and getPackageName() (and some MetaData).
I propose an extension of this interface, providing access to agendaGroup, activationGroup and ruleFlowGroup. I see no obvious reason why these user defined attributes should remain hidden.
These rule attributes would provide a good opportunity for writing more sophisticated event loggers, letting you specify rule filters by natural rule groupings.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2620) ActivationCreatedEvent - Activation: InitialFactImpl in Object set
by Wolfgang Laun (JIRA)
ActivationCreatedEvent - Activation: InitialFactImpl in Object set
----------------------------------------------------------------------
Key: JBRULES-2620
URL: https://jira.jboss.org/browse/JBRULES-2620
Project: Drools
Issue Type: Bug
Security Level: Public (Everyone can see)
Components: drools-api
Affects Versions: 5.1.0.FINAL
Reporter: Wolfgang Laun
Assignee: Mark Proctor
Fix For: 5.1.1.FINAL
Given this rule
rule "show no gaps"
when
not Gap()
then
System.out.println( "No gaps!" );
end
the ActivationCreatedEvent references an Activation, where the list of fact handles (getFactHandles) contains one element, but its Object is null:
Fact null @0:0:27032609:1306428912:0:DEFAULT
But the list of objects (getObjects) returns a list where there *is* an object:
Object (org.drools.reteoo.InitialFactImpl): org.drools.reteoo.InitialFactImpl@4dde85f0
This should be changed; neither a fact handle nor an object should be returned if there are no user objects participating in the activation.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2774) CCE when using undeclared events
by Wolfgang Laun (JIRA)
CCE when using undeclared events
---------------------------------
Key: JBRULES-2774
URL: https://jira.jboss.org/browse/JBRULES-2774
Project: Drools
Issue Type: Bug
Security Level: Public (Everyone can see)
Affects Versions: 5.1.1.FINAL
Reporter: Wolfgang Laun
Assignee: Mark Proctor
Fix For: 5.2.0.M1
It may not be possible to avoid a runtime error because the parser does not "understand" temporal operators although it should not be impossible to add this. But is should be possible to produce an error message that clearly indicates the problem, e.g., "Cannot use operator xxx on fact type YYY which is not an event" or "YYY must be declared with @role(event) when using temporal operators".
Omitting the declares for events, as in this DRL:
/**
declare CallStart
@role( event )
@timestamp( time )
end
declare CallEnd
@role( event )
@timestamp( time )
end
**/
rule "match-start-end"
when
$start: CallStart( $s: source, $d: destination, $st: time )
not CallStart( this before $start )
$end: CallEnd( source == $s, destination == $d, $et: time )
not CallEnd( source == $s, destination == $d, this before $end )
then
//...
end
results in a runtime exception:
Exception in thread "main" java.lang.ClassCastException: org.drools.common.DefaultFactHandle cannot be cast to org.drools.common.EventFactHandle
at org.drools.base.evaluators.BeforeEvaluatorDefinition$BeforeEvaluator.evaluateCachedRight(BeforeEvaluatorDefinition.java:316)
at org.drools.rule.VariableRestriction.isAllowedCachedRight(VariableRestriction.java:117)
at org.drools.rule.VariableConstraint.isAllowedCachedRight(VariableConstraint.java:121)
at org.drools.common.SingleBetaConstraints.isAllowedCachedRight(SingleBetaConstraints.java:151)
at org.drools.reteoo.NotNode.assertObject(NotNode.java:140)
at org.drools.reteoo.CompositeObjectSinkAdapter.doPropagateAssertObject(CompositeObjectSinkAdapter.java:450)
at org.drools.reteoo.CompositeObjectSinkAdapter.propagateAssertObject(CompositeObjectSinkAdapter.java:378)
at org.drools.reteoo.ObjectTypeNode.assertObject(ObjectTypeNode.java:190)
at org.drools.reteoo.EntryPointNode.assertObject(EntryPointNode.java:145)
at org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:1174)
at org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:1123)
at org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:917)
at org.drools.impl.StatefulKnowledgeSessionImpl.insert(StatefulKnowledgeSessionImpl.java:251)
at call.Main.execute(Main.java:90)
at call.Main.main(Main.java:100)
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months
[JBoss JIRA] Created: (JBRULES-2773) Rule delayed although temporal operator within not() refers to past events
by Wolfgang Laun (JIRA)
Rule delayed although temporal operator within not() refers to past events
--------------------------------------------------------------------------
Key: JBRULES-2773
URL: https://jira.jboss.org/browse/JBRULES-2773
Project: Drools
Issue Type: Bug
Security Level: Public (Everyone can see)
Affects Versions: 5.1.1.FINAL
Reporter: Wolfgang Laun
Assignee: Mark Proctor
Fix For: 5.2.0.M1
The .drl:
declare Leave
@role( event )
@timestamp( timestamp )
end
rule "XXX Leave not !="
when
$leave: Leave()
not Leave( this != $leave )
then
System.out.println( "XXX only one Leave - not !=" );
end
rule "YYY Leave not after"
when
$leave: Leave()
not Leave( this before $leave )
then
System.out.println( "YYY only one Leave - not before" );
end
A) The pseudo-clock is advanced according to the timestamp; then
exactly one event Leave is inserted; then fireAllRules() is called.
1) Running in CLOUD mode, both rules fire.
2) But running in STREAM mode, ONLY rule XXX fires.
B) Like A, but the session clock is advanced by (at least) 1ms
prior to calling fireAllRules().
3) Either mode, both rules fire.
I think that A2) is incorrect; why should passing another msec change the logic? Rule YYY matches by looking into the past, so the "rule activation delay" described in 2.5.2.2. Negative Patterns in Stream Mode should not apply because the default parameter for before is [1ms,...].
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 2 months