首页 > 解决方案 > Drools 没有按预期工作。未应用规则

问题描述

下午好,我是流口水的菜鸟,我正在尝试通过举例来学习。

我的示例处理应用规则以对订单的某些产品征税的经典问题,因此我有两个类,订单和产品,如下所示:

订单类

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


}

产品类别

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>

两个问题,请,我做错了什么以便流口水没有应用规则,一旦应用规则,我如何从引擎中恢复对象?

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

标签: javadrools

解决方案


你只有一个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从订单中获得的方式有点不稳定......不确定你在那里尝试做什么。)


推荐阅读