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
的方式有点不稳定……不确定您在那里尝试做什么。)
下午好,我是流口水的菜鸟,正在学习学习中
我的示例处理 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
的方式有点不稳定……不确定您在那里尝试做什么。)