You
need no-loop on the rules because of the call to “modify(s)” . Modify changes
the fact in working memory and the engine is
automatically notified of the changes at the end of the modify block. After modify the
same rule could hit again as the conditions are still true.
The
first rule doesn’t need the no-loop it because of the check “recommendPurchase
== null”
Joe
From:
rules-users-bounces@lists.jboss.org
[mailto:rules-users-bounces@lists.jboss.org] On Behalf Of Bryan Hansen
Sent: Sunday, November 02, 2008 8:21 PM
To: rules-users@lists.jboss.org
Subject: [rules-users] no-loop usage question
I have been reading through the documentation and trying
some of the tutorials and have a question about the no-loop attribute.
Not really relevant to the post, but I figured I would mention it, I have been
following this post and updating it to use the current version of Drools. http://www.onjava.com/pub/a/onjava/2005/08/03/drools.html?page=7
I have written my rules as such:
package org.drools.examples
import org.drools.examples.StockOffer;
rule PriceBelow100
dialect "java"
when
s: StockOffer( stockPrice < 100
&& recommendPurchase == null )
then
modify( s ) {
setRecommendPurchase(StockOffer.YES)
}
end
rule NegativeStockPrice
dialect "java"
no-loop true
when
s: StockOffer( stockPrice < 0 )
then
modify( s ) {
setRecommendPurchase(StockOffer.NO)
}
end
rule DontBuyXYZStock
dialect "java"
no-loop true
when
s: StockOffer(stockName ==
"XYZ" && stockPrice < 10 )
then
modify( s ) {
setRecommendPurchase(StockOffer.YES)
}
end
rule BuyXYZStock
dialect "java"
no-loop true
when
s: StockOffer(stockName ==
"XYZ" && stockPrice > 10 )
then
modify( s ) {
setRecommendPurchase(StockOffer.NO)
}
end
My question is, why do I have to put no-loop on every rule (except for the
first). After the first time through the rules, it shouldn't be modifying to
where the rules would fire it again. Am I doing something wrong with how my
rules are written? My sample data is this:
package org.drools.examples;
import org.drools.examples.BusinessLayer;
import org.drools.examples.StockOffer;
import junit.framework.TestCase;
/*
* JUnit test for the business rules in the
* application.
*
* This also acts a 'simulator' for the business
* rules - allowing us to specify the inputs,
* examine the outputs and see if they match our
* expectations before letting the code loose in
* the real world.
*/
public class BusinessRuleTest extends TestCase {
/**
* Tests the purchase of a stock
*/
public void testStockBuy() throws Exception {
// Create a Stock with simulated values
StockOffer testOffer = new StockOffer();
testOffer.setStockName("MEGACORP");
testOffer.setStockPrice(22);
testOffer.setStockQuantity(1000);
// Run the rules on it
BusinessLayer.evaluateStockPurchase(testOffer);
// Is it what we expected?
assertTrue(testOffer.getRecommendPurchase() != null);
assertTrue("YES".equals(testOffer.getRecommendPurchase()));
}
/**
* Tests the purchase of a stock makes sure the system
will not accept
* negative numbers.
*/
public void testNegativeStockBuy() throws Exception {
// Create a Stock with our simulated
values
StockOffer testOffer = new StockOffer();
testOffer.setStockName("MEGACORP");
testOffer.setStockPrice(-22);
testOffer.setStockQuantity(1000);
// Run the rules on it
BusinessLayer.evaluateStockPurchase(testOffer);
// Is it what we expected?
assertTrue("NO".equals(testOffer.getRecommendPurchase()));
}
/**
* Makes sure the system will buy stocks of XYZ corp
only if it really cheap
*/
public void testXYZStockBuy() throws Exception {
// Create a Stock with our simulated
values
StockOffer testOfferLow = new
StockOffer();
StockOffer testOfferHigh = new
StockOffer();
testOfferLow.setStockName("XYZ");
testOfferLow.setStockPrice(9);
testOfferLow.setStockQuantity(1000);
testOfferHigh.setStockName("XYZ");
testOfferHigh.setStockPrice(11);
testOfferHigh.setStockQuantity(1000);
// Run the rules on it and test
BusinessLayer.evaluateStockPurchase(testOfferLow);
assertTrue("YES".equals(testOfferLow.getRecommendPurchase()));
BusinessLayer.evaluateStockPurchase(testOfferHigh);
assertTrue("NO".equals(testOfferHigh.getRecommendPurchase()));
}
}
I can post up all the code if this isn't enough to answer the question.
Thanks!