To stick to the subject, I have a strange problem (stack
trace in PS) with a rule containing two accumulate calls,
the result of the first one is re-injected as the input of
the second one. Those accumulate functions are "home
made".
The first one (tokenize) returns an ArrayList of Token
objects built by tokenizing the "text" of the Sentence
objects.
The second one (build10windows) returns an ArrayList of
Window objects, each one them containing 10 consecutive
tokens.
Here is the rule
when
$budget : ManualAnnotation(text == "something") $tokens : java.util.ArrayList() from
accumulate ($s : Sentence(), tokenize($s))
$windows : java.util.ArrayList() from
accumulate ($t : Token() from $tokens, build10windows($t))
# removed a part here but the problem occurs
even without this part
then
retract($budget);
Is there anything else one should be aware of when
implementing their own accumulate function? I mean things
related to the fact that "classical" accumulate functions
(sum, average) return an immutable object that does not
share anything with the context object.
Although accumulate, reverse, and getResult methods of my
functions are unit tested, I suspect something that could
be related to stateless/stateful considerations.
What do you think?
Many thanks,
Bruno.
PS :
The stack trace is:
at
org.drools.runtime.rule.impl.DefaultConsequenceExceptionHandler.handleException(DefaultConsequenceExceptionHandler.java:39)
at
org.drools.common.DefaultAgenda.fireActivation(DefaultAgenda.java:927)
at
org.drools.common.DefaultAgenda.fireNextItem(DefaultAgenda.java:856)
at
org.drools.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1071)
at
org.drools.common.AbstractWorkingMemory.fireAllRules(AbstractWorkingMemory.java:785)
at
org.drools.common.AbstractWorkingMemory.fireAllRules(AbstractWorkingMemory.java:751)
at
org.drools.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:218)
at
org.drools.command.runtime.rule.FireAllRulesCommand.execute(FireAllRulesCommand.java:99)
at
org.drools.command.runtime.rule.FireAllRulesCommand.execute(FireAllRulesCommand.java:33)
at
org.drools.command.runtime.BatchExecutionCommandImpl.execute(BatchExecutionCommandImpl.java:159)
at
org.drools.command.runtime.BatchExecutionCommandImpl.execute(BatchExecutionCommandImpl.java:81)
at
org.drools.impl.StatelessKnowledgeSessionImpl.execute(StatelessKnowledgeSessionImpl.java:262)
... 5 more
Caused by: java.lang.NullPointerException
at
org.drools.reteoo.AccumulateNode.getFirstMatch(AccumulateNode.java:967)
at
org.drools.reteoo.AccumulateNode.splitList(AccumulateNode.java:920)
at
org.drools.reteoo.AccumulateNode.removePreviousMatchesForLeftTuple(AccumulateNode.java:874)
at
org.drools.reteoo.AccumulateNode.retractLeftTuple(AccumulateNode.java:205)
at
org.drools.reteoo.CompositeLeftTupleSinkAdapter.doPropagateRetractLeftTuple(CompositeLeftTupleSinkAdapter.java:238)
at
org.drools.reteoo.CompositeLeftTupleSinkAdapter.propagateRetractLeftTupleDestroyRightTuple(CompositeLeftTupleSinkAdapter.java:138)
at
org.drools.reteoo.AccumulateNode.retractLeftTuple(AccumulateNode.java:212)
at
org.drools.reteoo.ObjectTypeNode.retractObject(ObjectTypeNode.java:240)
at
org.drools.reteoo.EntryPointNode.retractObject(EntryPointNode.java:231)
at
org.drools.common.AbstractWorkingMemory.retract(AbstractWorkingMemory.java:1288)
at
org.drools.base.DefaultKnowledgeHelper.retract(DefaultKnowledgeHelper.java:201)
at
org.drools.base.DefaultKnowledgeHelper.retract(DefaultKnowledgeHelper.java:214)
at
defaultpkg.Rule_Display_windows_0.defaultConsequence(Rule_Display_windows_0.java:21)
at
defaultpkg.Rule_Display_windows_0DefaultConsequenceInvoker.evaluate(Rule_Display_windows_0DefaultConsequenceInvoker.java:29)
at
org.drools.common.DefaultAgenda.fireActivation(DefaultAgenda.java:917)
... 15 more
Bruno.
Le 24/08/2011 16:21, Edson Tirelli a écrit :
Yes, evaluation is incremental, so
for every new fact, it will call accumulate() and
getResult().
We do want to reduce the calls to
getResult(), improving performance, but it is not
easy to figure out a way, as from an engine
perspective, it never knows when the application
is done inserting facts and it is time to
calculate the final result.
While testing my custom accumulation function
I noticed an unexpected
behavior (th'ats of course a personal point of
view).
It seems that Drools 5.1 calls accumulate(...)
and getResult(...) as
many times as the number of accumulated facts
(accumulate, getResult,
accumulate, getResult, etc...).
Is it supposed to work like this?