简单示例如果执行则无限循环。 如果我添加“无循环真”,它的工作原理。但为什么?没有环洞...
package spikes;
import org.springframework.roo.addon.javabean.RooJavaBean;
@RooJavaBean
public class Applicant {
private final String string;
private final int age;
public boolean valid=true;
public Applicant(String string, int i) {
this.string = string;
this.age = i;
}
}
DroolsSpikeTest
package spikes;
import static org.junit.Assert.*;
import org.drools.KnowledgeBase;
import org.drools.runtime.StatelessKnowledgeSession;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:**/applicationContext-drools.xml"})
public class DroolsSpikeTest {
@Autowired
private KnowledgeBase kbase;
@Test
public void testspikeDroolRule() {
StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
Applicant a = new Applicant("Mr John Smith", 16);
assertTrue(a.isValid());
ksession.execute(a);
assertFalse(a.isValid());
}
}
的applicationContext-drools.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--INFO: http://architects.dzone.com/articles/drools-51-expands-spring -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:drools="http://drools.org/schema/drools-spring"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://drools.org/schema/drools-spring http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-container/drools-spring/src/main/resources/org/drools/container/spring/drools-spring-1.0.0.xsd">
<drools:kbase id="kbase1">
<drools:resources>
<drools:resource id="licenseRule" type="DRL" source="classpath:spikes/licenseApplication.drl"/>
</drools:resources>
<drools:configuration>
<drools:mbeans enabled="true" />
</drools:configuration>
</drools:kbase>
<drools:ksession kbase="kbase1" type="stateless" id="ksessionStateless" name="stateless1" >
</drools:ksession>
</beans>
licenseApplication.drl
import spikes.Applicant
rule "Is of valid age" when
$a : Applicant( age < 18 )
then
modify( $a ) { valid = false };
end
答案 0 :(得分:10)
以modify($a)
开头的行告诉引擎申请人事实已更新。这会导致引擎重新评估所有规则条件。由于申请人的年龄仍然低于18岁,这会导致此规则再次激活。永远冲洗并重复。
添加no-loop
告诉引擎规则的后果不应导致相同的规则重新激活。请注意no-loop
不是无限循环的银弹;如果规则A的结果导致规则B激活,并且规则B的结果导致规则A激活,no-loop
将不会阻止无限循环。
就个人而言,我认为no-loop
是一个骗局,可以绕过写出更好的条件。更好的解决方案是以不应该重新激活的方式编写条件。有时这涉及插入您的条件引用的“控制事实”,但您通常可以简单地更新模式以使其更具体。在您的情况下,解决方案很简单:
rule "Is of valid age" when
$a : Applicant( age < 18, valid != false )
then
modify( $a ) { valid = false };
end
通过向您的模式添加valid != false
,修改该事实不会导致此规则重新激活。