2012-01-20 2 views
5

Простые примерные петли до бесконечности, если выполнены. Если я добавлю «no-loop true», это сработает. Но почему? Там нет петли дыра ...Drools срабатывает в петле

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

Я никогда не видел, чтобы «петлевое отверстие» означало «вызывать неожиданную петлю». – aitchnyu

ответ

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 к вашей модели, модификация факта не заставит это правило реактивировать.

Смежные вопросы