Drools优惠券生成规则触发次数超出预期问题排查
Drools优惠券规则重复触发问题排查
我是Drools新手,正在跟着《Mastering JBoss Drools 6》第二章的示例学习。这个示例需要创建Customer和Order对象,实现以下逻辑:
- 订单包含5个商品的客户,归类为
SILVER等级 - 单价超过500的商品,归类为
HIGH_RANGE SILVER等级客户需要生成Coupon- 订单商品数≥2的
SILVER客户可享受10%折扣
我写了对应的规则和测试用例,预期规则总触发次数是8次(5次商品分类+1次客户分类+1次折扣规则+1次优惠券生成),但实际触发了9次,其中优惠券生成规则触发了两次。测试日志显示优惠券生成规则执行了两次,但最终只能查到第二个优惠券;调试模式下触发次数符合预期(8次)。后续排查发现:用Lombok的@EqualsAndHashCode注解,或者自定义包含discount字段的hashCode方法时会出现这个问题,只保留equals方法就恢复正常。
相关规则代码
add-discount.drl
rule "High Range order - 10% discount" when $o: Order($lines: orderLines, orderLines.size >= 2, $customer: customer, discount == null) $c: Customer(category == Customer.Category.SILVER, this == $customer) forall( OrderLine(this memberOf $lines, $item: item) Item(this == $item, category == Item.Category.HIGH_RANGE) ) then modify($o){ setDiscount(new Discount(10.0)) } end
classify-customer-rules.drl
rule "Classify Customer by order size" when $o: Order( orderLines.size >= 5, $customer: customer ) $c: Customer(this == $customer, category == Customer.Category.NA) then modify($c){ setCategory(Customer.Category.SILVER) } end
classify-items-rules.drl
rule "Classify Item - Low Range" when $i: Item(cost < 200, category == Category.NA) then $i.setCategory(Category.LOW_RANGE); update($i); end rule "Classify Item - Mid Range" when $i: Item(cost > 200 && cost < 500, category == Category.NA) then $i.setCategory(Category.MID_RANGE); update($i); end rule "Classify Item - High Range" when $i: Item(cost >= 500, category == Category.NA) then $i.setCategory(Category.HIGH_RANGE); update($i); end
coupons-creation.drl
rule "Create Coupons for silver customer" when $o: Order($customer: customer) $c: Customer(this == $customer, category == Customer.Category.SILVER) then Coupon x = new Coupon($c, $o, Coupon.CouponType.POINTS); System.out.println(x); insert(x); end
测试代码
@Test void orderDiscountTest() { KieSession kieSession = Util.getDefaultKieSession(); Order o = ModelFactory.getOrderWithFiveHighRangeItems(); kieSession.insert(o.getCustomer()); kieSession.insert(o.getOrderLines().get(0)); kieSession.insert(o.getOrderLines().get(1)); kieSession.insert(o.getOrderLines().get(2)); kieSession.insert(o.getOrderLines().get(3)); kieSession.insert(o.getOrderLines().get(4)); kieSession.insert(o.getOrderLines().get(0).getItem()); kieSession.insert(o.getOrderLines().get(1).getItem()); kieSession.insert(o.getOrderLines().get(2).getItem()); kieSession.insert(o.getOrderLines().get(3).getItem()); kieSession.insert(o.getOrderLines().get(4).getItem()); kieSession.insert(o); int fired = kieSession.fireAllRules(); assertEquals(8, fired); assertEquals(Customer.Category.SILVER, o.getCustomer().getCategory()); assertNotNull(o.getDiscount()); assertEquals(10.0, o.getDiscount().getPercentage()); assertEquals(Item.Category.HIGH_RANGE, o.getOrderLines().get(0).getItem().getCategory()); assertEquals(Item.Category.HIGH_RANGE, o.getOrderLines().get(1).getItem().getCategory()); assertEquals(Item.Category.HIGH_RANGE, o.getOrderLines().get(2).getItem().getCategory()); assertEquals(Item.Category.HIGH_RANGE, o.getOrderLines().get(3).getItem().getCategory()); assertEquals(Item.Category.HIGH_RANGE, o.getOrderLines().get(4).getItem().getCategory()); Collection<Coupon> coupons = Util.getFactsFromSession(kieSession, Coupon.class); coupons.forEach(x -> System.out.println(x)); assertEquals(1, coupons.size()); }
测试日志
12:54:47.607 [main] DEBUG org.drools.core.impl.KnowledgeBaseImpl - Starting Engine in PHREAK mode 12:54:47.730 [main] DEBUG org.drools.core.common.DefaultAgenda - State was INACTIVE is nw FIRING_ALL_RULES 12:54:47.732 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop 12:54:47.795 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop Coupon created com.example.droolstut.model.Coupon@b14cb989 12:54:47.797 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop 12:54:47.797 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop 12:54:47.799 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop 12:54:47.806 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop Coupon created com.example.droolstut.model.Coupon@424f842a 12:54:47.806 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop 12:54:47.806 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop 12:54:47.806 [main] DEBUG org.drools.core.common.DefaultAgenda - State was FIRING_ALL_RULES is nw HALTING 12:54:47.806 [main] DEBUG org.drools.core.common.DefaultAgenda - State was HALTING is nw INACTIVE Coupon found: com.example.droolstut.model.Coupon@424f842a Coupon found: com.example.droolstut.model.Coupon@424f842a
排查补充信息
EDIT 1日志
Order(orderId=1, date=Thu Jan 01 05:30:00 IST 1970, customer=Customer(customerId=1, age=40, name=John Doe, email=johndoe@example.com, category=SILVER), orderLines=[OrderLine(item=com.example.droolstut.model.Item@38c70399, quantity=1), OrderLine(item=com.example.droolstut.model.Item@5245e3d4, quantity=1), OrderLine(item=com.example.droolstut.model.Item@6bc4c40f, quantity=1), OrderLine(item=com.example.droolstut.model.Item@8543a44a, quantity=1), OrderLine(item=com.example.droolstut.model.Item@9ec28485, quantity=1)], state=PENDING, discount=null) Customer(customerId=1, age=40, name=John Doe, email=johndoe@example.com, category=SILVER) com.example.droolstut.model.Coupon@2753dad2 12:16:02.399 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop 12:16:02.400 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop 12:16:02.402 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop 12:16:02.408 [main] DEBUG org.drools.core.common.DefaultAgenda - Fire Loop Order(orderId=1, date=Thu Jan 01 05:30:00 IST 1970, customer=Customer(customerId=1, age=40, name=John Doe, email=johndoe@example.com, category=SILVER), orderLines=[OrderLine(item=com.example.droolstut.model.Item@5dc27ea9, quantity=1), OrderLine(item=com.example.droolstut.model.Item@77415ee4, quantity=1), OrderLine(item=com.example.droolstut.model.Item@90c03f1f, quantity=1), OrderLine(item=com.example.droolstut.model.Item@aa3f1f5a, quantity=1), OrderLine(item=com.example.droolstut.model.Item@c3bdff95, quantity=1)], state=PENDING, discount=Discount(percentage=10.0)) Customer(customerId=1, age=40, name=John Doe, email=johndoe@example.com, category=SILVER) com.example.droolstut.model.Coupon@10e5ecb2
EDIT 2自定义hashCode与equals方法
@Override public int hashCode() { int hash = 3; hash = 17 * hash + Objects.hashCode(this.orderId); hash = 17 * hash + Objects.hashCode(this.date); hash = 17 * hash + Objects.hashCode(this.customer); hash = 17 * hash + Objects.hashCode(this.orderLines); hash = 17 * hash + Objects.hashCode(this.state); hash = 17 * hash + Objects.hashCode(this.discount); return hash; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Order other = (Order) obj; if (!Objects.equals(this.orderId, other.orderId)) { return false; } if (!Objects.equals(this.date, other.date)) { return false; } if (!Objects.equals(this.customer, other.customer)) { return false; } if (!Objects.equals(this.orderLines, other.orderLines)) { return false; } if (this.state != other.state) { return false; } if (!Objects.equals(this.discount, other.discount)) { return false; } return true; }
内容的提问来源于stack exchange,提问作者Karthik
相关产品推荐
相关产品推荐

