[jboss-jira] [JBoss JIRA] (DROOLS-1537) Scheduled activations are rescheduled as if new when unmarshalling session in Drools 6.5
Mario Fusco (JIRA)
issues at jboss.org
Wed Apr 26 05:17:02 EDT 2017
[ https://issues.jboss.org/browse/DROOLS-1537?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13398170#comment-13398170 ]
Mario Fusco commented on DROOLS-1537:
-------------------------------------
What you're doing wrong in your test case is unmarshalling the ksession against a kbase that is different from the one you used for marshalling. This is not allowed and if you need incremental compilation you should use the KieScanner.
I'm pasting below a simplified version of your test case. I tried it against master and it works as expected.
{code}
public static KieSession marshallAndUnmarshall(KieBase kbase, KieSession ksession, KieSessionConfiguration sessionConfig) {
// Serialize and Deserialize
try {
Marshaller marshaller = KieServices.Factory.get().getMarshallers().newMarshaller(kbase);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
marshaller.marshall(baos, ksession);
marshaller = MarshallerFactory.newMarshaller( kbase );
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
baos.close();
ksession = marshaller.unmarshall(bais, sessionConfig, null);
bais.close();
} catch (Exception e) {
e.printStackTrace();
fail("unexpected exception :" + e.getMessage());
}
return ksession;
}
@Test
public void testSnapshotRecoveryScheduledRulesPlain() throws Exception {
// DROOLS-1537
String drl = "package com.drools.restore.reproducer\n" +
"global java.util.List list;\n" +
"global java.util.List list2;\n" +
"rule R1\n" +
" timer (int: 20s)\n" +
" when\n" +
" $m : String( this == \"Hello World1\" )\n" +
" then\n" +
" list.add( $m );\n" +
" retract( $m );\n" +
"end\n" +
"rule R2\n" +
" timer (int: 30s)\n" +
" when\n" +
" $m : String( this == \"Hello World2\" )\n" +
" then\n" +
" list2.add( $m );\n" +
" retract( $m );\n" +
"end\n";
KieSessionConfiguration ksconf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
ksconf.setOption( ClockTypeOption.get( ClockType.PSEUDO_CLOCK.getId() ) );
ksconf.setOption( TimedRuleExecutionOption.YES );
ksconf.setOption(TimerJobFactoryOption.get("trackable"));
ksconf.setOption(ClockTypeOption.get("pseudo"));
KieHelper helper = new KieHelper();
helper.addContent( drl, ResourceType.DRL );
KieBase kbase = helper.build( EventProcessingOption.STREAM );
KieSession ksession = kbase.newKieSession( ksconf, null );
PseudoClockScheduler timeService = (PseudoClockScheduler) ksession.<SessionClock> getSessionClock();
List list = new ArrayList();
ksession.setGlobal("list", list);
List list2 = new ArrayList();
ksession.setGlobal("list2", list2);
ksession.insert("Hello World1");
ksession.insert("Hello World2");
ksession.fireAllRules();
timeService.advanceTime(10500, TimeUnit.MILLISECONDS);
ksession = marshallAndUnmarshall( kbase, ksession, ksconf );
ksession.fireAllRules();
long accumulatedSleepTime = 0;
for (int i = 0; i < 6; i++) {
timeService.advanceTime(5050, TimeUnit.MILLISECONDS);
accumulatedSleepTime += 5050;
assertEquals( i < 1 ? 0 : 1, list.size() );
assertEquals( i < 3 ? 0 : 1, list2.size() );
}
}
{code}
However I've found a bug also in this. In fact if after deserialization I retake the pseudo clock instance from the deserialized ksession
{code}
PseudoClockScheduler timeService2 = (PseudoClockScheduler) ksession.<SessionClock> getSessionClock();
{code}
and then in the for loop I do the advance on this second instance I get an Exception like the one I'm pasting below. I'll investigate this further problem immediately.
{code}
11:08:41.029 [main] WARN o.d.c.t.impl.DefaultTimerJobInstance.call:81 - Unable to execute timer job!
org.kie.api.runtime.rule.ConsequenceException: Exception executing consequence for rule "R1" in com.drools.restore.reproducer: java.lang.NullPointerException
at org.drools.core.runtime.rule.impl.DefaultConsequenceExceptionHandler.handleException(DefaultConsequenceExceptionHandler.java:39) ~[classes/:na]
at org.drools.core.common.DefaultAgenda.handleException(DefaultAgenda.java:1256) ~[classes/:na]
at org.drools.core.phreak.RuleExecutor.innerFireActivation(RuleExecutor.java:440) ~[classes/:na]
at org.drools.core.phreak.RuleExecutor.fireActivation(RuleExecutor.java:382) ~[classes/:na]
at org.drools.core.phreak.RuleExecutor.fire(RuleExecutor.java:136) ~[classes/:na]
at org.drools.core.phreak.RuleExecutor.fire(RuleExecutor.java:93) ~[classes/:na]
at org.drools.core.phreak.PhreakTimerNode$TimerAction.evaluateAndFireRule(PhreakTimerNode.java:441) ~[classes/:na]
at org.drools.core.phreak.PhreakTimerNode$TimerAction.execute(PhreakTimerNode.java:433) ~[classes/:na]
at org.drools.core.phreak.SynchronizedPropagationList$1.execute(SynchronizedPropagationList.java:51) ~[classes/:na]
at org.drools.core.common.DefaultAgenda.executeTask(DefaultAgenda.java:1169) ~[classes/:na]
at org.drools.core.phreak.SynchronizedPropagationList.addEntry(SynchronizedPropagationList.java:47) ~[classes/:na]
at org.drools.core.common.DefaultAgenda.addPropagation(DefaultAgenda.java:1268) ~[classes/:na]
at org.drools.core.impl.StatefulKnowledgeSessionImpl.addPropagation(StatefulKnowledgeSessionImpl.java:2057) ~[classes/:na]
at org.drools.core.phreak.PhreakTimerNode$TimerNodeJob.execute(PhreakTimerNode.java:372) ~[classes/:na]
at org.drools.core.time.SelfRemovalJob.execute(SelfRemovalJob.java:34) ~[classes/:na]
at org.drools.core.time.impl.DefaultTimerJobInstance.call(DefaultTimerJobInstance.java:69) [classes/:na]
at org.drools.core.time.impl.DefaultTimerJobInstance.call(DefaultTimerJobInstance.java:30) [classes/:na]
at org.drools.core.time.impl.PseudoClockScheduler.runCallBacksAndIncreaseTimer(PseudoClockScheduler.java:208) [classes/:na]
at org.drools.core.time.impl.PseudoClockScheduler.advanceTime(PseudoClockScheduler.java:160) [classes/:na]
at org.drools.compiler.integrationtests.marshalling.MarshallingTest.testSnapshotRecoveryScheduledRulesPlain(MarshallingTest.java:2939) [test-classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_92]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_92]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_92]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_92]
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) [junit-4.12.jar:4.12]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) [junit-4.12.jar:4.12]
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) [junit-4.12.jar:4.12]
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) [junit-4.12.jar:4.12]
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) [junit-4.12.jar:4.12]
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) [junit-rt.jar:na]
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51) [junit-rt.jar:na]
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237) [junit-rt.jar:na]
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) [junit-rt.jar:na]
Caused by: java.lang.NullPointerException: null
at org.drools.core.phreak.RuleExecutor.innerFireActivation(RuleExecutor.java:427) ~[classes/:na]
... 39 common frames omitted
{code}
> Scheduled activations are rescheduled as if new when unmarshalling session in Drools 6.5
> ----------------------------------------------------------------------------------------
>
> Key: DROOLS-1537
> URL: https://issues.jboss.org/browse/DROOLS-1537
> Project: Drools
> Issue Type: Bug
> Affects Versions: 6.5.0.Final
> Reporter: Kay J
> Assignee: Mario Fusco
> Attachments: RestoreReproducer.java
>
>
> Ticket representing question/bug from drools user group: https://groups.google.com/forum/#!topic/drools-usage/Gy3uhkh6J78
> Hello Drools users,
> I found an anomaly in Drools 6.5. I insert an Event, which triggers a rule with a timer after some time. For backup reasons I marshal the session inbetween to back it up and on unmarshal it later. However, after unmarshalling it, the scheduled activations are sometimes scheduled as if just inserted (e.g. 1min scheduling, with marshal/unmarshal after 25s results in the activation firing after 85 (25+60) seconds instead of actual 60s. I know this worked with Drools 5.6 consistently, but now it sometimes works, sometimes not, which is indeterministic.
> I created a test reproducing this behaviour, which has changing output whenever you execute it. What the example does: It create a scheduled activation, which should trigger after 20s. After 10s the session is marshalled, destroyed and unmarshalled into a new session. After another 10s it should finally trigger. (10s + 10s -> the 20s scheduled).
--
This message was sent by Atlassian JIRA
(v7.2.3#72005)
More information about the jboss-jira
mailing list