简体   繁体   English

Drools 没有按预期工作。 规则不适用

[英]Drools is not working as expected. Rules are not applied

􏰧􏰉􏰙􏰑Good afternoon, I'm a rookie with drools, I'm trying to learn by making an example. 􏰧􏰉􏰙􏰑大家下午好,我是一个流口水的菜鸟,努力学习学习。

My example deals with the classic problem of applying rules in order to tax some products of an order, so I have two classes, Order and Product, something like that:我的示例处理应用规则以对订单的某些产品征税的经典问题,因此我有两个类,Order 和 Product,类似于:

Order class订单类

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class Order {

private String id;
private List<Product> products;
private double totalPrize;
private double totalTaxes;

public Order() {
    super();
    this.id=UUID.randomUUID().toString();
    this.products = new ArrayList<Product>();
    this.totalPrize = 0d;
    this.totalTaxes = 0d;

}

public List<Product> getProducts() {
    return products;
}

public void addProduct(Product p) {
    this.products.add(p);
}
public double getTotalPrize() {
    return totalPrize;
}
public void setTotalPrize(double totalPrize) {
    this.totalPrize += totalPrize;
}
public double getTotalTaxes() {
    return totalTaxes;
}
public void setTotalTaxes(double totalTaxes) {
    this.totalTaxes += totalTaxes;
}

@Override
public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("Order [id=").append(id).append(", products=").append(products).append(", totalPrize=")
            .append(totalPrize).append(", totalTaxes=").append(totalTaxes).append("]");
    return builder.toString();
}


}

Product class产品类别

import java.util.UUID;

public class Product {

private String id;
private String description;
private double prize;
private boolean imported;
private boolean tax_exempt;
private double sale_tax;

public Product(String description, double prize) {
    super();
    this.id=UUID.randomUUID().toString();
    this.description = description;
    this.prize = prize;
    this.tax_exempt = description.matches("(.*)book(.*)") || 
                      description.matches("(.*)food(.*)") || 
                      description.matches("(.*)medical(.*)");

    this.imported = description.matches("(.*)imported(.*)");

}

public double getPrize() {
    return prize;
}

public boolean isImported() {
    return imported;
}


public boolean isTax_exempt() {
    return tax_exempt;
}

public double getSale_tax() {
    return sale_tax;
}

public void setSale_tax(double sale_tax) {
    this.sale_tax = sale_tax;
}

@Override
public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("Product [id=").append(id).append(", description=").append(description).append(", prize=")
            .append(prize).append(", imported=").append(imported).append(", tax_exempt=").append(tax_exempt)
            .append(", sale_tax=").append(sale_tax).append("]");
    return builder.toString();
}

}

Order has a list of products, if the product is imported, i will apply a tax of 5%.订单有产品清单,如果产品是进口的,我将征收 5% 的税。 I apply a product to be taxed using a boolean.我使用布尔值应用要征税的产品。

this is how i create the order and chain it to kSession:这就是我创建订单并将其链接到 kSession 的方式:

  //This is part of main mathod. 
  public static Order createOrder2() {
    /*
     * 
     * 1 imported box of chocolate 10.00
     * 1 imported bottle of perfume 47.50
     * */
    Product p1 = new Product("imported food box of chocolate", 10.00d); //exempted and imported
    Product p2 = new Product("imported bottle of perfume",14.99); //not exempted imported

    Order order = new Order();
    order.addProduct(p1);
    order.addProduct(p2);

    return order;
}


@Inject
@KSession
private KieSession kSession;

// instantiating order2 from above method.

kSession.insert(order2);
kSession.fireAllRules();
// end of main class

This is part of the rules file这是规则文件的一部分

rule "Applying taxes to imported products."
when
    $order: Order()
    $products: Product() from $order.getProducts()
    $product: Product($products.isImported())
then
    $product.setSale_tax($product.getPrize() *5d/100);  
    $order.setTotalPrize($product.getSale_tax() + $product.getPrize());
    $order.setTotalTaxes($product.getSale_tax());
    System.out.println($order.toString());
    System.out.println($order.getTotalPrize()); 
    System.out.println($order.getTotalTaxes());
end

I insert an order to kSession and fired the rules and when i run a test method, i got this output in terminal and test fails.我向 kSession 插入一个订单并触发了规则,当我运行一个测试方法时,我在终端中得到了这个输出并且测试失败。

Test method:测试方法:

@Test
public void should_apply_rules_to_order1_exempted_imported_not_imported() {
    //GIVEN
    Assert.assertNotNull(kSession);
    final Order order1 = Utilities.createOrder1();
    //WHEN
    kSession.insert(order1);

    //THEN
    Assert.assertEquals(1, kSession.fireAllRules());
    Assert.assertEquals("Shoud be equals...",29.83d, order1.getTotalPrize(),0d);
    Assert.assertEquals("Shoud be equals...",1.50d, order1.getTotalTaxes(),0d);
}

This is the pom.xml file:这是 pom.xml 文件:

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.aironman.test.rumbo</groupId>
<artifactId>TaxPlanner</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>A pet test project</description>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <kie.version>6.3.0.Final</kie.version>
    <junit.version>4.11</junit.version>
    <cdi.version>1.2</cdi.version>
    <weld.version>2.3.0.Final</weld.version>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.jboss.arquillian</groupId>
            <artifactId>arquillian-bom</artifactId>
            <version>1.1.10.Final</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.kie</groupId>
        <artifactId>kie-api</artifactId>
        <version>${kie.version}</version>
    </dependency>
    <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-compiler</artifactId>
        <version>${kie.version}</version>
    </dependency>
    <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-core</artifactId>
        <version>${kie.version}</version>
    </dependency>
    <dependency>
        <groupId>javax.enterprise</groupId>
        <artifactId>cdi-api</artifactId>
        <version>${cdi.version}</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.weld.se</groupId>
        <artifactId>weld-se-core</artifactId>
        <version>${weld.version}</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.arquillian.junit</groupId>
        <artifactId>arquillian-junit-container</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.arquillian.container</groupId>
        <artifactId>arquillian-weld-se-embedded-1.1</artifactId>
        <version>1.0.0.CR9</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Two questions, please, what do am i doing wrong in order drools is not applying the rule, and how can i recover the object from the engine once rules are applied?请问两个问题,我做错了什么才能让drools不应用规则,以及一旦应用规则,我如何从引擎中恢复对象?

@ioannis-barakos, i saw in a previous post you helped another guy with similar problem, could you help me? @ioannis-barakos,我在之前的帖子中看到你帮助了另一个有类似问题的人,你能帮帮我吗?

You only have an Order in working memory, not a Product so your rule doesn't trigger.您在工作内存中只有一个Order ,而不是一个Product因此您的规则不会触发。 The rule will only trigger when all of the conditions on the left hand side (the "when" clause) match.该规则仅在左侧的所有条件(“when”子句)匹配时才会触发。

The following rule should be more like you expect:以下规则应该更符合您的预期:

dialect "mvel"

rule "Applying taxes to imported products."
when

  // Take the order from working memory and get the product list from it
  $order: Order( $products: products != null )

  // Get only the imported products
  $product: Product( isImported == true ) from $products
then
  $product.setSale_tax($product.getPrize() * (5d/100));  
  $order.setTotalPrize($product.getSale_tax() + $product.getPrize());
  $order.setTotalTaxes($product.getSale_tax());
  System.out.println($order.toString());
  System.out.println($order.getTotalPrize()); 
  System.out.println($order.getTotalTaxes());
end

The first thing we do is get the product list from the order and alias it to $products .我们做的第一件事是从订单中获取产品列表并将其别名为$products Then we get the imported products from that list -- notice the from $products .然后我们从该列表中获取进口产品——注意from $products

In your original, you were just calling $product: Product( ... ) which says "get me a product that looks like this from working memory. Since you didn't have anything in working memory, it didn't work.在你的原版中,你只是调用$product: Product( ... ) ,它说“从工作记忆中给我一个看起来像这样的产品。因为你在工作记忆中没有任何东西,所以它不起作用。

(Also the way you were getting the $products from the order was a little wonky... not sure what you were trying to do there.) (此外,您从订单中获取$products的方式有点不稳定……不确定您要在那里做什么。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM