2012-01-20 21 views
5

Bucles de ejemplo simple ad infinitum si se ejecuta. Si agrego "no-loop true", funciona. ¿Pero por qué? No hay ningún agujero del lazo ...Drools se activa en un bucle

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

Nunca vi 'loop hole' significa 'causar inesperadamente un bucle'. – aitchnyu

Respuesta

10

La línea que comienza con modify($a) le dice al motor que el hecho del solicitante se ha actualizado. Esto hace que el motor reevalúe todas las condiciones de la regla. Como la edad del solicitante todavía es menor de 18 años, esto hace que esta regla se active nuevamente. Enjuague y repita, para siempre.

Agregando no-loop le dice al motor que la consecuencia de una regla no debe hacer que la misma regla se reactive. Tenga en cuenta que no-loop no es una bala de plata contra infinitos bucles; si la consecuencia de la Regla A hace que se active la Regla B, y la consecuencia de la Regla B hace que se active la Regla A, no-loop no evitará el bucle infinito.

Personalmente, creo que no-loop es una trampa para evitar escribir mejores condiciones. La mejor solución para esto es escribir sus condiciones de tal manera que no se reactiven cuando no deberían. A veces esto implica insertar "hechos de control" que sus condiciones hacen referencia, pero a menudo puede simplemente actualizar el patrón para que sea más específico. En su caso, la solución es simple:

rule "Is of valid age" when 
    $a : Applicant(age < 18, valid != false) 
then 
    modify($a) { valid = false }; 
end 

Mediante la adición de valid != false a su patrón, la modificación del hecho no causará esta regla para volver a activar.

Cuestiones relacionadas