[
https://issues.jboss.org/browse/JBRULES-3466?page=com.atlassian.jira.plug...
]
Chris Dolan commented on JBRULES-3466:
--------------------------------------
Hmm, I've failed to reproduce the problem in a unit test. Below is my failed attempt.
If there are any useful diagnostics I can do on my real model, please let me know.
New file:
src/test/resources/org/drools/integrationtests/test_AccumulateReverseModifyInsertLogical.drl
{noformat}
package org.drools.test;
import org.drools.Cheese;
import org.drools.Cheesery;
import org.drools.Person;
global java.util.List results;
declare Total
person : Person
value : Number
end
rule "Total" salience 2
when
$person : Person( $likes : likes )
$total : Number() from accumulate( $c : Cheese( type == $likes ),
sum($c.getPrice()) )
then
insertLogical(new Total($person, $total));
end
rule "Minimum Total" salience 1
when
$min : Number() from accumulate( $p : Person(name != "Doug") and
$t : Total(person == $p),
min($t.getValue()) )
then
results.add( $min );
end
{noformat}
Modified file:
{noformat}
diff --git a/drools-compiler/src/test/java/org/drools/integrationtests/AccumulateTest.java
b/drools-compiler/src/test/java/org/drools/integrationtests/AccumulateTest.java
index 0c4db51..c37fe67 100644
--- a/drools-compiler/src/test/java/org/drools/integrationtests/AccumulateTest.java
+++ b/drools-compiler/src/test/java/org/drools/integrationtests/AccumulateTest.java
@@ -475,6 +475,93 @@ public class AccumulateTest extends CommonTestMethodBase {
}
@Test
+ public void testAccumulateReverseModifyInsertLogical() throws Exception {
+ // read in the source
+ final Reader reader = new InputStreamReader( getClass().getResourceAsStream(
"test_AccumulateReverseModifyInsertLogical.drl" ) );
+ final RuleBase ruleBase = loadRuleBase( reader );
+
+ final WorkingMemory wm = ruleBase.newStatefulSession();
+ final List results = new ArrayList();
+
+ wm.setGlobal( "results",
+ results );
+
+ final Cheese[] cheese = new Cheese[]{
+ new Cheese( "stilton", 10 ),
+ new Cheese( "stilton", 2 ),
+ new Cheese( "stilton", 5 ),
+ new Cheese( "brie", 15 ),
+ new Cheese( "brie", 16 ),
+ new Cheese( "provolone", 8 )
+ };
+ final Person alice = new Person( "Alice", "brie" );
+ final Person bob = new Person( "Bob", "stilton" );
+ final Person carol = new Person( "Carol", "cheddar" );
+ final Person doug = new Person( "Doug", "stilton" );
+
+ final FactHandle[] cheeseHandles = new FactHandle[cheese.length];
+ for ( int i = 0; i < cheese.length; i++ ) {
+ cheeseHandles[i] = wm.insert( cheese[i] );
+ }
+ final FactHandle aliceHandle = wm.insert( alice );
+ final FactHandle bobHandle = wm.insert( bob );
+ // add Carol later
+ final FactHandle dougHandle = wm.insert( doug ); // should be ignored
+
+ wm.fireAllRules();
+ System.out.println("results: " + results);
+ assertEquals( 17, ((Number) results.get( results.size() - 1 )).intValue() );
+
+ wm.retract(cheeseHandles[1]);
+ wm.fireAllRules();
+ System.out.println("results: " + results);
+ assertEquals( 15, ((Number) results.get( results.size() - 1 )).intValue() );
+
+ bob.setLikes( "provolone" );
+ wm.update( bobHandle, bob );
+ wm.fireAllRules();
+ System.out.println("results: " + results);
+ assertEquals( 8, ((Number) results.get( results.size() - 1 )).intValue() );
+
+ wm.retract(cheeseHandles[5]);
+ wm.fireAllRules();
+ System.out.println("results: " + results);
+ assertEquals( 0, ((Number) results.get( results.size() - 1 )).intValue() );
+
+ wm.retract(bobHandle);
+ wm.fireAllRules();
+ System.out.println("results: " + results);
+ assertEquals( 31, ((Number) results.get( results.size() - 1 )).intValue() );
+
+ final FactHandle carolHandle = wm.insert( carol );
+ wm.fireAllRules();
+ System.out.println("results: " + results);
+ assertEquals( 0, ((Number) results.get( results.size() - 1 )).intValue() );
+
+ FactHandle cheddarHandle = wm.insert(new Cheese("cheddar", 6));
+ wm.fireAllRules();
+ System.out.println("results: " + results);
+ assertEquals( 6, ((Number) results.get( results.size() - 1 )).intValue() );
+
+ wm.retract(cheddarHandle);
+ wm.fireAllRules();
+ System.out.println("results: " + results);
+ assertEquals( 0, ((Number) results.get( results.size() - 1 )).intValue() );
+
+ wm.retract(aliceHandle);
+ wm.retract(carolHandle);
+ wm.retract(dougHandle);
+ wm.fireAllRules();
+ System.out.println("results: " + results);
+ assertEquals( Integer.MAX_VALUE, ((Number) results.get( results.size() - 1
)).intValue() );
+
+ wm.insert(alice);
+ wm.fireAllRules();
+ System.out.println("results: " + results);
+ assertEquals( 31, ((Number) results.get( results.size() - 1 )).intValue() );
+ }
+
+ @Test
public void testAccumulateReverseModifyMVEL() throws Exception {
// read in the source
final Reader reader = new InputStreamReader( getClass().getResourceAsStream(
"test_AccumulateReverseModifyMVEL.drl" ) );
{noformat}
sum with no matching values results in NPE on reverse
-----------------------------------------------------
Key: JBRULES-3466
URL:
https://issues.jboss.org/browse/JBRULES-3466
Project: Drools
Issue Type: Bug
Security Level: Public(Everyone can see)
Components: drools-core (expert)
Affects Versions: 5.4.0.CR1
Environment: drools-planner 5.4.0-SNAPSHOT, snapshot downloaded on Apr 9, 2012
Reporter: Chris Dolan
Assignee: Edson Tirelli
I have a rule with this element in the when clause:
{noformat}
$beforePrediction : Number() from accumulate(
JobSlot(job != NULL_JOB, $j : job, $service == service, $ordinal >
ordinal) and $p : Prediction(job == $j, service == $service),
sum($p.getMillisMid())
)
{noformat}
When I execute this I have cases where there are no matching Prediction instances, so the
sum is zero. Later on retract, I get this:
{noformat}
Caused by: java.lang.NullPointerException: null
at
org.drools.base.accumulators.SumAccumulateFunction.reverse(SumAccumulateFunction.java:83)
at
org.drools.base.accumulators.JavaAccumulatorFunctionExecutor.reverse(JavaAccumulatorFunctionExecutor.java:130)
at org.drools.rule.Accumulate.reverse(Accumulate.java:208)
{noformat}
The relevant code is this:
{noformat}
public void accumulate(Serializable context,
Object value) {
SumData data = (SumData) context;
data.total += ((Number) value).doubleValue();
}
{noformat}
and this:
{noformat}
public void reverse(Object workingMemoryContext,
Object context,
Tuple leftTuple,
InternalFactHandle handle,
Declaration[] declarations,
Declaration[] innerDeclarations,
WorkingMemory workingMemory) throws Exception {
final Object value = ((JavaAccumulatorFunctionContext)
context).reverseSupport.remove( Integer.valueOf( handle.getId() ) );
this.function.reverse( ((JavaAccumulatorFunctionContext) context).context,
value );
}
{noformat}
A breakpoint reveals that handle is a Prediction instance. Somehow that handle was not
added to reverseSupport, apparently.
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators:
https://issues.jboss.org/secure/ContactAdministrators!default.jspa
For more information on JIRA, see:
http://www.atlassian.com/software/jira