Thanks wolfgang, for the info and that workaround.<br>I think there is some off by one error in for loop, or may be some mistake that I didnt notice in my code. the following rule with 3 objects gives index out of bound error. I am attaching java &amp; drl file (package com.example.drools.testing). I am using 5.2.0 final release.<br>
<br>rule &quot;Buy X units of Product A and Get Y units of Product B Free&quot;<br>    when<br>        $itemsA : ArrayList( $a : size &gt;= 2 ) from collect( CartItem( productId == &quot;A&quot;, processed == false) )<br>
        $itemsB : ArrayList( $b : size &gt;= 1 ) from collect( CartItem( productId == &quot;B&quot;, processed == false) )<br>        $m : RuleMessage()<br> then<br>         $m.addMessage(&quot;sizes- A=&quot;+$a + &quot; B=&quot;+$b);<br>
         int $x = 2;<br>        int $y = 1;<br>        $m.addMessage(&quot;sizes- X=&quot;+$x + &quot; Y=&quot;+$y);<br>        for(int i=0 ; i &lt; $x ; i++){<br>             CartItem $ci = (CartItem) $itemsA.get(i);<br>
             $m.addMessage( $ci.getId()+&quot;)Found item: &quot;+$ci.getProductId());<br>             modify((CartItem)$ci){<br>                setProcessed(true),<br>                setPromoItemDiscount(0D),<br>                setPromoId(&quot;2&quot;),<br>
                setBundleId(bundler.getId()),<br>                setAggregatorId(1)<br>            };<br>         };<br>         for(int i=0 ; i &lt; $y  ; i++){<br>         CartItem $ci = (CartItem) $itemsB.get(i);<br>             $m.addMessage( $ci.getId()+&quot;)Found item: &quot;+$ci.getProductId());<br>
             modify((CartItem)$ci){<br>                setProcessed(true),<br>                setPromoItemDiscount($ci.getPrice()),<br>                setPromoId(&quot;2&quot;),<br>                setBundleId(bundler.getId()),<br>
                setAggregatorId(2)<br>            };<br>         };<br>        bundler.increment();<br>end<br><br><br><b>error</b><br>Exception in thread &quot;main&quot; org.drools.runtime.rule.ConsequenceException: rule: Buy X units of Product A and Get Y units of Product B Free<br>
<br>    at org.drools.runtime.rule.impl.DefaultConsequenceExceptionHandler.handleException(DefaultConsequenceExceptionHandler.java:39)<br>    at org.drools.common.DefaultAgenda.fireActivation(DefaultAgenda.java:916)<br>    at org.drools.common.DefaultAgenda.fireNextItem(DefaultAgenda.java:845)<br>
    at org.drools.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1056)<br>    at org.drools.common.AbstractWorkingMemory.fireAllRules(AbstractWorkingMemory.java:733)<br>    at org.drools.common.AbstractWorkingMemory.fireAllRules(AbstractWorkingMemory.java:699)<br>
    at org.drools.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:218)<br>    at com.example.drools.testing.Main.main(Main.java:52)<br>Caused by: java.lang.IndexOutOfBoundsException: Index: 1, Size: 1<br>
    at java.util.ArrayList.RangeCheck(ArrayList.java:547)<br>    at java.util.ArrayList.get(ArrayList.java:322)<br>    at com.example.drools.testing.Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.defaultConsequence(Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java:12)<br>
    at com.example.drools.testing.Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0DefaultConsequenceInvoker.evaluate(Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0DefaultConsequenceInvoker.java:44)<br>
    at org.drools.common.DefaultAgenda.fireActivation(DefaultAgenda.java:906)<br>    ... 6 more<br><br><br><div class="gmail_quote">2011/9/9 Wolfgang Laun <span dir="ltr">&lt;<a href="mailto:wolfgang.laun@gmail.com">wolfgang.laun@gmail.com</a>&gt;</span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">If the declared type of productId and getProductId() is String, it should be compared to a string literal. (A conversion might be made, but don&#39;t rely on that.)<br>
<br>You cannot access components of a global in RHS code using the simplified notation (not unless you use &quot;mvel&quot; - but don&#39;t do that.) Here, all accesses should be written the usual Java way, with getter and setter calls.<br>

<br>The problem you have with modify(ci) is a bug (fixed for 5.3.0). As a workaround,use<br><br>modify( (CartItem)ci ){ ... }<br><font color="#888888"><br>-W</font><div><div></div><div class="h5"><br> <br><br>2011/9/9 Sandeep Bandela <span dir="ltr">&lt;<a href="mailto:gibsosmat@gmail.com" target="_blank">gibsosmat@gmail.com</a>&gt;</span><br>

<div class="gmail_quote"><blockquote class="gmail_quote" style="border-left:1px solid rgb(204, 204, 204);margin:0pt 0pt 0pt 0.8ex;padding-left:1ex">some more info for the modify() problem, the CartItem is an interface and the implementation is CartItemImpl. if this info leads to some clues. <br>

</blockquote><blockquote class="gmail_quote" style="border-left:1px solid rgb(204, 204, 204);margin:0pt 0pt 0pt 0.8ex;padding-left:1ex"><div><div></div><div><br><br><div class="gmail_quote">On Fri, Sep 9, 2011 at 1:28 PM, Sandeep Bandela <span dir="ltr">&lt;<a href="mailto:gibsosmat@gmail.com" target="_blank">gibsosmat@gmail.com</a>&gt;</span> wrote:<br>


<blockquote class="gmail_quote" style="border-left:1px solid rgb(204, 204, 204);margin:0pt 0pt 0pt 0.8ex;padding-left:1ex">Hi here is the same thing converted to mvl<br><br>// this Bundler.java has integer member that keeps incrementing<br>

global Bundler bundler<div>
<br><br>rule &quot;Apply 10% discount if you purchase 2 items&quot;<br></div>    when<br>
        $s1 : CartItem( <b>productId == 219759</b>, processed == false)<br>        $s2 : CartItem( this != $s1, productId == $s1.productId, processed == false)<div><br>        $m : RuleMessage()<br> then<br>        $m.addMessage(&quot;Found item1: &quot; + $s1.getName() + &quot; id: &quot;+$s1.getId());<br>



        $m.addMessage(&quot;Found item2: &quot; + $s2.getName() + &quot; id: &quot;+$s2.getId());<br>        modify($s1){<br>        setProcessed(true),<br>        setPromoItemDiscount($s1.getPrice() * 0.1),<br>        setPromoId(&quot;1&quot;),<br>



        setBundleId(bundler.getId()),<br>        setAggrigatorId(1)<br>        };<br>        modify($s2){<br>        setProcessed(true),<br>        setPromoItemDiscount($s2.getPrice() * 0.1),<br>        setPromoId(&quot;1&quot;),<br>



        setBundleId(bundler.getId()),<br>        setAggrigatorId(1)<br>        };<br></div>        $m.addMessage(&quot;bundled [&quot;+<b>bundler.getId()</b>+&quot;] &quot;+$s1.getId()+&quot;,&quot;+$s2.getId());<br>        bundler.increment();<br>



end<br><br>the above rule dosent fire, but if I change the highlighter to getProductId() == 219759, or use productId == &quot;219759&quot;, may be this is some edge case but it took long time for me to figure it out productId is String. now consider the <b>bundler.getId()</b>, if I use <b><a href="http://bundler.id" target="_blank">bundler.id</a></b> I get compilation error.<br>



<br>Rule Compilation error : [Rule name=&#39;Apply 10% discount if you purchase 2 items&#39;]<br>    com/example/promotions/promotionEngine/Rule_Apply_10__discount_if_you_purchase_2_items_0.java (23:1592) : The field Bundler.id is not visible<br>



2011-09-09 13:18:39,863  INFO [STDOUT] - 2011-09-09 13:18:39,863  INFO [PromotionsManager] - ksession initialized<br>2011-09-09 13:18:39,863  INFO [STDOUT] - 2011-09-09 13:18:39,863  INFO [PromotionsManager] - Exploding items and inserting cart<br>



2011-09-09 13:18:39,864  INFO [STDOUT] - 2011-09-09 13:18:39,863 ERROR [CheckOutBasedUtilities] - Failed to apply promo offers <br>java.lang.RuntimeException: Unexpected global [bundler]<br>    at org.drools.common.AbstractWorkingMemory.setGlobal(AbstractWorkingMemory.java:613)<br>



    at org.drools.impl.StatefulKnowledgeSessionImpl.setGlobal(StatefulKnowledgeSessionImpl.java:332)<br>    at com.example.promotions.promotionEngine.PromotionsManager.applyOffers(PromotionsManager.java:154)<br>    at com.example.promotions.promotionEngine.PromotionsManager.shuffleForOffers(PromotionsManager.java:61)`<br>



<br>lastly my actual problem that I am looking for a solution lets say we have &quot;Buy X items of A and get Y Items of B&quot;. X=5 &amp; Y=4 from the original problem I want to template the rule and load the values of X,A,Y,B from database or excel etc. if I use modify the error is as follows<br>



<br><b>my rule</b><div><br><br><br>rule &quot;Buy X units of Product A and Get Y units of Product B Free&quot;<br></div>    when<br>        $itemsX : ArrayList( size == 2 ) from collect( CartItem( getProductId() == 24257, !isProcessed()))<br>



        $itemsY : ArrayList( size == 1) from collect(CartItem( getProductId() == 24260, !isProcessed()))<br>        $m : RuleMessage()<br> then<br>         for(Object item : $itemsX){<br>             CartItem ci = (CartItem) item;<br>



             $m.addMessage( ci.getId()+&quot;)Found item: &quot;+ci.getItemId()+&quot; name: &quot;+ci.getName());<br>             modify(ci){<br>                setProcessed(true),<br>                setPromoItemDiscount(0),<div>


<br>
                setPromoId(&quot;2&quot;),<br>                setBundleId(bundler.getId()),<br>                setAggrigatorId(1)<br>            };<br>         }<br></div>         for(Object item : $itemsY){<br>         CartItem ci = (CartItem) item;<br>



             $m.addMessage( ci.getId()+&quot;)Found item: &quot;+ci.getItemId()+&quot; name: &quot;+ci.getName());<br>             modify(ci){<br>                setProcessed(true),<br>                setPromoItemDiscount(ci.getPrice()),<br>



                setPromoId(&quot;2&quot;),<br>                setBundleId(bundler.getId()),<br>                setAggrigatorId(2)<br>            };<br>         }<br>        bundler.increment();<br>end<br><br>Rule Compilation error : [Rule name=&#39;Buy X units of Product A and Get Y units of Product B Free&#39;]<br>



    com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java (11:1236) : The method setProcessed(boolean) is undefined for the type Object<br>    com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java (12:1265) : The method setPromoItemDiscount(int) is undefined for the type Object<br>



    com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java (13:1299) : The method setPromoId(String) is undefined for the type Object<br>    com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java (14:1325) : The method setBundleId(Integer) is undefined for the type Object<br>



    com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java (15:1364) : The method setAggrigatorId(int) is undefined for the type Object<br>    com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java (22:1702) : The method setProcessed(boolean) is undefined for the type Object<br>



    com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java (23:1731) : The method setPromoItemDiscount(Double) is undefined for the type Object<br>    com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java (24:1777) : The method setPromoId(String) is undefined for the type Object<br>



    com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java (25:1803) : The method setBundleId(Integer) is undefined for the type Object<br>    com/example/promotions/promotionEngine/Rule_Buy_X_units_of_Product_A_and_Get_Y_units_of_Product_B_Free_0.java (26:1842) : The method setAggrigatorId(int) is undefined for the type Object<br>



<br>Rule Compilation error : [Rule name=&#39;Apply 10% discount if you purchase 2 items&#39;]<br>    com/example/promotions/promotionEngine/Rule_Apply_10__discount_if_you_purchase_2_items_0.java (23:1592) : The field Bundler.id is not visible<div>


<div></div><div><br>
<br><br><div class="gmail_quote">On Fri, Sep 9, 2011 at 12:40 PM, Sandeep Bandela <span dir="ltr">&lt;<a href="mailto:gibsosmat@gmail.com" target="_blank">gibsosmat@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left:1px solid rgb(204, 204, 204);margin:0pt 0pt 0pt 0.8ex;padding-left:1ex">



Hi Wolfgang,<br>This is what I did initially but for product &gt; 2 I didnt find a generic way to do this. following is my first rule. I didnt use field names because it was giving error that member is not accessible. I will attach the errors of each case in a few mins.<br>




<br>rule &quot;Apply 10% discount if you purchase 2 items&quot;<br>    dialect &quot;java&quot;<br>    when<br>        $s1 : CartItem( getProductId() == 236061, !isProcessed())<br>        $s2 : CartItem( getProductId() == 236061, getId() != $s1.getId(), !isProcessed())<br>




        $m : RuleMessage()<br> then<br>        $m.addMessage(&quot;Found item1: &quot; + $s1.getName() + &quot; id: &quot;+$s1.getId());<br>        $m.addMessage(&quot;Found item2: &quot; + $s2.getName() + &quot; id: &quot;+$s2.getId());<br>




        modify($s1){<br>        setProcessed(true),<br>        setPromoItemDiscount($s1.getPrice() * 0.1),<br>        setPromoId(&quot;1&quot;),<br>        setBundleId(bundler.getId()),<br>        setAggrigatorId(1)<br>        };<br>




        modify($s2){<br>        setProcessed(true),<br>        setPromoItemDiscount($s2.getPrice() * 0.1),<br>        setPromoId(&quot;1&quot;),<br>        setBundleId(bundler.getId()),<br>        setAggrigatorId(1)<br>        };<br>




        bundler.increment();<br>end<div><div></div><div><br><br><div class="gmail_quote">2011/9/9 Wolfgang Laun <span dir="ltr">&lt;<a href="mailto:wolfgang.laun@gmail.com" target="_blank">wolfgang.laun@gmail.com</a>&gt;</span><br>



<blockquote class="gmail_quote" style="border-left:1px solid rgb(204, 204, 204);margin:0pt 0pt 0pt 0.8ex;padding-left:1ex">
Your rule exhibits procedural thinking. (For an aspiring rule programmer his is typical teething troubles.) <br><br>There&#39;s no need to collect all A&#39;s and B&#39;s in order to determine their number being greater than one or two - this is achieved automatically by a simple triple match rule. Consider<br>





<br>rule &quot;2A - 1B&quot;<br>when<br>   $a1: CartItem( productId == &quot;A&quot;, processed == false )<br>   $a2: CartItem( this != $a1, productId == &quot;A&quot;, processed == false )<br>   $b: CartItem( productId == &quot;B&quot;, processed == false )<br>





then<br>   modify( $a1 ){...}<br>   modify( $a2 ){...}<br>   modify( $b ){...}<br>end<br><br>Note:<br><ul><li>The modify is essential. (When you say &quot;doesn&#39;t work&quot;, always provide details.)</li><li>Use the field name rather than the getter call - it improves readability.</li>





<li>I&#39;m not sure whether 5.2.0 final handles boolean fields correctly - IIRC, there were some issues. It&#39;s possible that CartItem(..., !processed) works. <br></li></ul>-W<br><br><div class="gmail_quote"><div><div>




</div><div>2011/9/8 Sandeep Bandela <span dir="ltr">&lt;<a href="mailto:gibsosmat@gmail.com" target="_blank">gibsosmat@gmail.com</a>&gt;</span><br>
</div></div><blockquote class="gmail_quote" style="border-left:1px solid rgb(204, 204, 204);margin:0pt 0pt 0pt 0.8ex;padding-left:1ex"><div><div></div><div>Hi,<br>I am new to rules engine, after going through the examples shipped (shopping.drl, petstore.drl)<br>





I am trying to implement promotional discounting using drools 5.2.0 final, stateful session. assume cart has all the items that customer wants to buy,<br>

I am trying to bundle them together with the existing offers<br><br>rule &quot;Buy X units of Product A and Get Y units of Product B Free&quot;<br>    dialect &quot;java&quot;<br>
when<br>    $itemsA : ArrayList( size &gt;= 2) from collect( CartItem( getProductId() == &quot;A&quot;, !isProcessed()))<br>    $itemsB : ArrayList( size &gt;= 1) from collect( CartItem( getProductId() == &quot;B&quot;, !isProcessed()))<br>







then<br>    // current scenario buy 2*A and get 1*B <br>    int x = 2;<br>    int y = 1;<br>    for(int i=0 ; i &lt; x ; i++){<br>        CartItem $ci = (CartItem) $itemsA.get(i);<br>        // modify($ci){setProcessed(true) ... } dosent work<br>







        $ci.setProcessed(true);<br>        $ci.setItemDiscount(0.0);<br>        $ci.setBundleId(bundler.getId());<br>    }<br>    <br>    for(int i=0 ; i &lt; y  ; i++){<br>        CartItem $ci = (CartItem) $itemsB.get(i);<br>







        $ci.setProcessed(true);<br>        $ci.setItemDiscount($ci.getPrice());<br>        $ci.setBundleId(bundler.getId());<br>    }<br>    // global counter to identify bundled items<br>    bundler.increment();<br>end<br>







<br>the above rule calculates only for 1 set of offer i.e first 2*A &amp; 1*B are considered, rest in the cart are not bundled.<br>if customer buys 4*A + 2*B it dosent consider it. am I missing anything? is this the right way to do it?<br>







any feedback is appreciated.<br><br><br><br clear="all"><br>-- <br>Regards,<br><font color="#888888">Sandeep Bandela.<br><br>
</font><br></div></div>_______________________________________________<br>
rules-users mailing list<br>
<a href="mailto:rules-users@lists.jboss.org" target="_blank">rules-users@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/rules-users" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>
<br></blockquote></div><br>
<br>_______________________________________________<br>
rules-users mailing list<br>
<a href="mailto:rules-users@lists.jboss.org" target="_blank">rules-users@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/rules-users" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>
<br></blockquote></div><br><br clear="all"><br></div></div>-- <br>Regards,<br><font color="#888888">Sandeep Bandela.<br><br>
</font></blockquote></div><br><br clear="all"><br></div></div>-- <br>Regards,<br><font color="#888888">Sandeep Bandela.<br><br>
</font></blockquote></div><br><br clear="all"><br></div></div>-- <br>Regards,<br><font color="#888888">Sandeep Bandela.<br><br>
</font><br>_______________________________________________<br>
rules-users mailing list<br>
<a href="mailto:rules-users@lists.jboss.org" target="_blank">rules-users@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/rules-users" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>
<br></blockquote></div><br>
</div></div><br>_______________________________________________<br>
rules-users mailing list<br>
<a href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/rules-users" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>
<br></blockquote></div><br><br clear="all"><br>-- <br>Regards,<br>Sandeep Bandela.<br><br>