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