[rules-users] Using variables as map keys in MVEL in LHS

Steve Ronderos steve.ronderos at ni.com
Thu Jul 16 09:04:07 EDT 2009


Hello,

Again, I'm working on converting my project that used Drools 4.0.7 to 
5.0.1.

I've run across a problem with a rule that accesses a map in the LHS using 
a variable as the key.  When MVEL tries to resolve this, it appears that 
it is not evaluating the variable before accessing the map.  I've modified 
the Shopping example from the Drools 5.0.1 Examples to recreate the issue 
in a simpler setting.

This is the rule (I removed all the other rules for this example)
rule "Cart notification"
    salience 10

    when
        $p : Product( $productName : name)
        $c : Customer( cart[$productName] == $p) 
    then
        System.out.println( "Customer " + $c.name + " has " + $p.name + " 
in cart");
end 

I added the following to the Customer class:

private Map<String,Product> cart = new HashMap<String, Product>();
public Map<String, Product> getCart() {
    return cart;
}

and I modified the main method to be:

public static final void main(String[] args) throws Exception {
    final KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.
newKnowledgeBuilder();
    kbuilder.add( ResourceFactory.newClassPathResource( "Shopping.drl", 
ShoppingExample.class ),
                          ResourceType.DRL );

    final KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
    kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );

    final StatefulKnowledgeSession ksession = 
kbase.newStatefulKnowledgeSession();

    Customer mark = new Customer( "mark",
                                  0 );
    ksession.insert( mark );

    Product shoes = new Product( "shoes",
                                 60 );
    ksession.insert( shoes );
 
    mark.getCart().put("shoes", shoes);
 
    ksession.fireAllRules();
}

So basically, I added a map to Customer, inserted one item and made a rule 
that will use a variable as a key for that map. 
What I would expect to happen is:
  the Product pattern would match the shoes Product that is inserted into 
the ksession, the $productName variable would contain the value "shoes"
  the Customer fact, mark, would be matched with the second pattern in the 
rule because cart["shoes"] should resolve to the shoes fact which is $p in 
the rule
  The message should print

What actually happens is an error message:

Exception in thread "main" org.drools.RuntimeDroolsException: Exception 
executing predicate cart[$productName] == $p
        at org.drools.rule.PredicateConstraint.isAllowedCachedLeft(
PredicateConstraint.java:302)
        at org.drools.common.SingleBetaConstraints.isAllowedCachedLeft(
SingleBetaConstraints.java:138)
        at org.drools.reteoo.JoinNode.assertLeftTuple(JoinNode.java:114)
        at 
org.drools.reteoo.SingleLeftTupleSinkAdapter.doPropagateAssertLeftTuple(
SingleLeftTupleSinkAdapter.java:117)
        at 
org.drools.reteoo.SingleLeftTupleSinkAdapter.createAndPropagateAssertLeftTuple(
SingleLeftTupleSinkAdapter.java:78)
        at org.drools.reteoo.LeftInputAdapterNode.assertObject(
LeftInputAdapterNode.java:142)
        at 
org.drools.reteoo.SingleObjectSinkAdapter.propagateAssertObject(
SingleObjectSinkAdapter.java:42)
        at org.drools.reteoo.ObjectTypeNode.assertObject(
ObjectTypeNode.java:185)
        at org.drools.reteoo.EntryPointNode.assertObject(
EntryPointNode.java:146)
        at org.drools.common.AbstractWorkingMemory.insert(
AbstractWorkingMemory.java:1046)
        at org.drools.common.AbstractWorkingMemory.insert(
AbstractWorkingMemory.java:1001)
        at org.drools.common.AbstractWorkingMemory.insert(
AbstractWorkingMemory.java:788)
        at org.drools.impl.StatefulKnowledgeSessionImpl.insert(
StatefulKnowledgeSessionImpl.java:216)
        at org.drools.examples.ShoppingExample.main(
ShoppingExample.java:32)
Caused by: [Error: unable to resolve method: 
java.util.HashMap.$productName() [arglength=0]]
[Near : {... Unknown ....}]
             ^
[Line: 1, Column: 0]
        at 
org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getMethod(
ReflectiveAccessorOptimizer.java:906)
        at 
org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getBeanProperty(
ReflectiveAccessorOptimizer.java:585)
        at 
org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(
ReflectiveAccessorOptimizer.java:313)
        at 
org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.optimizeAccessor(
ReflectiveAccessorOptimizer.java:138)
        at org.mvel2.ast.ASTNode.getReducedValueAccelerated(
ASTNode.java:133)
        at org.mvel2.compiler.ExecutableAccessor.getValue(
ExecutableAccessor.java:37)
        at 
org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getCollectionProperty(
ReflectiveAccessorOptimizer.java:633)
        at 
org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(
ReflectiveAccessorOptimizer.java:319)
        at 
org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.optimizeAccessor(
ReflectiveAccessorOptimizer.java:138)
        at org.mvel2.ast.ASTNode.getReducedValueAccelerated(
ASTNode.java:133)
        at org.mvel2.ast.BinaryOperation.getReducedValueAccelerated(
BinaryOperation.java:102)
        at org.mvel2.MVELRuntime.execute(MVELRuntime.java:85)
        at org.mvel2.compiler.CompiledExpression.getValue(
CompiledExpression.java:104)
        at org.mvel2.MVEL.executeExpression(MVEL.java:978)
        at org.drools.base.mvel.MVELPredicateExpression.evaluate(
MVELPredicateExpression.java:75)
        at org.drools.rule.PredicateConstraint.isAllowedCachedLeft(
PredicateConstraint.java:295)
        ... 13 more

Is this a bug in MVEL or Drools, or am I using the map access incorrectly?

Thanks,

Steve Ronderos
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20090716/2dd696a4/attachment.html 


More information about the rules-users mailing list