Слюни загораются в петле - PullRequest
5 голосов
/ 20 января 2012

Простой пример циклов до бесконечности, если выполняется.Если я добавлю «без цикла правда», это работает.Но почему?Нет петлевого отверстия ...

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

1 Ответ

10 голосов
/ 20 января 2012

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

...