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

Drools is not working as expected. Rules are not applied

下午好,我是流口水的菜鸟,正在学习学习中

我的示例处理 classic 应用规则以便对订单的某些产品征税的问题,所以我有两个 classes,订单和产品,类似的东西:

订单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();
}


}

产品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();
}

}

订单有产品清单,如果产品是进口的,我会申请5%的税。我使用布尔值申请要征税的产品。

这就是我创建订单并将其链接到 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

这是规则文件的一部分

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

我向 kSession 插入一个命令并触发规则,当我 运行 一个测试方法时,我在终端中得到这个输出并且测试失败。

测试方法:

@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);
}

这是 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>

请问两个问题,为了 drools 不应用规则,我做错了什么?一旦应用了规则,我如何从引擎中恢复对象?

@ioannis-barakos,我在之前看到 post 你帮助了另一个遇到类似问题的人,你能帮帮我吗?

您的工作记忆中只有 Order,没有 Product,因此您的规则不会触发。只有当左侧的所有条件("when" 子句)匹配时,规则才会触发。

以下规则应该更符合您的预期:

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

我们做的第一件事是从订单中获取产品列表并将其别名为 $products。然后我们从该列表中获取进口产品——注意 from $products.

在您的原始版本中,您只是调用 $product: Product( ... ),它说“从工作记忆中给我一个看起来像这样的产品。由于您在工作记忆中没有任何东西,所以它不起作用。

(另外,您从订单中获取 $products 的方式有点不稳定……不确定您在那里尝试做什么。)