Drools 5.0.1GA upgrade
beve May 26, 2009 9:43 AMI'm updating Drools to 5.0.1.GA and discovered an issue with the business_ruleservice_stateful quickstart.
The following exception was shown when running the quickstart:
org.drools.RuntimeDroolsException: Exception executing predicate customer.userName == $c.userName at org.drools.rule.PredicateConstraint.isAllowedCachedLeft(PredicateConstraint.java:302) at org.drools.common.SingleBetaConstraints.isAllowedCachedLeft(SingleBetaConstraints.java:138) at org.drools.reteoo.AccumulateNode.assertLeftTuple(AccumulateNode.java:153) at org.drools.reteoo.CompositeLeftTupleSinkAdapter.doPropagateAssertLeftTuple(CompositeLeftTupleSinkAdapter.java:145) at org.drools.reteoo.CompositeLeftTupleSinkAdapter.createAndPropagateAssertLeftTuple(CompositeLeftTupleSinkAdapter.java:57) 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.jboss.internal.soa.esb.services.rules.DroolsRuleService.insertObjectsIntoWorkingMemory(DroolsRuleService.java:602) at org.jboss.internal.soa.esb.services.rules.DroolsRuleService.executeStatefulRules(DroolsRuleService.java:527) at org.jboss.internal.soa.esb.services.rules.DroolsRuleService.executeStatefulRules(DroolsRuleService.java:223) at org.jboss.internal.soa.esb.services.rules.RuleServiceCallHelper.executeRulesService(RuleServiceCallHelper.java:126) at org.jboss.soa.esb.actions.BusinessRulesProcessor.executeRulesService(BusinessRulesProcessor.java:121) at org.jboss.soa.esb.actions.BusinessRulesProcessor.process(BusinessRulesProcessor.java:97) at org.jboss.soa.esb.listeners.message.ActionProcessingPipeline.processPipeline(ActionProcessingPipeline.java:634) at org.jboss.soa.esb.listeners.message.ActionProcessingPipeline.processPipeline(ActionProcessingPipeline.java:586) at org.jboss.soa.esb.listeners.message.ActionProcessingPipeline.process(ActionProcessingPipeline.java:420) at org.jboss.soa.esb.listeners.message.MessageAwareListener$TransactionalRunner.run(MessageAwareListener.java:548) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675) at java.lang.Thread.run(Thread.java:595) Caused by: [Error: unable to access property (null parent): userName] [Near : {... Unknown ....}] ^ [Line: 1, Column: 0] at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getMethod(ReflectiveAccessorOptimizer.java:861) 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.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) ... 24 more
Three objects are inserted into the working memory which are:
1. ESB Message object instance.
2. OrderHeader object instance. This object has a customer field that is null.
3. Customer object instance which is not null.
Looking at our rules in OrderDiscountOnMultipleOrders.drl:
rule "Apply 10% discount to customer if totalPrice of all their orders is over 100" dialect "mvel" when $c : Customer() $i : Number(intValue >= 100) from accumulate ( OrderHeader( customer.userName == $c.userName, $totalAmount : totalAmount), sum( $totalAmount ) ); then $c.setOrderDiscount( 10 ); System.out.println( "Customer " + $c.getUserName() + " now has a shopping total of " + $i ); end
We are expecting the OrderHeader's customer to have been populated as we are using it to check the userName : "customer.userName == $c.userName".
How/why this worked with the previous version of Drools I'm not sure and need to find out. Perhaps the older version did a check for null first and the new version does not.
Anyway this seems to be an error with the quickstart and I've updated the src/org/jboss/soa/esb/samples/quickstart/businessrulesstateful/SetupMessage.java and now setting the customer on the header instance:
header.setCustomer(customer);
Also when upgrading I've noticed that a drools package (org.drools.rule.Package) that has been serialized with one version cannot be deserialized with another. You need to re-create the drl and store is in a pkg file. We do this in two places, one is in a unit test in the jbrules module and the other is in the business_ruleservice_ruleAgent quickstart. Both now have an ant target named "generatePackageFile" that will perform this task which can be used when upgrading. This info is also in the readme.txt of jbrules.
I also needed to remove the jndi.properties file from lib/ext/drools-persistence-jpa-5.0.1.jar which contained:
java.naming.factory.initial=bitronix.tm.jndi.BitronixInitialContextFactory
This was messing with our qa tests as we don't provide that class.
As always comments or questions are welcome.
/Daniel