Я обнаружил странное поведение двигателя слюни.У меня есть два правила с разными отличиями.Как описано в документации слюни
3.3.4.1.Разрешение конфликтов
Разрешение конфликтов требуется, когда в повестке дня несколько правил.(Основы этого описаны в главе «Быстрый запуск».) Поскольку запуск правила может иметь побочные эффекты для рабочей памяти, механизму правил необходимо знать, в каком порядке следует запускать правила (например, запуск правила A может вызвать правило B).должны быть удалены из повестки дня).
Стратегии разрешения конфликтов по умолчанию, используемые Drools: Значимость и LIFO (последний пришел, первый вышел).
Наиболее заметной является значимость (или приоритет).), в этом случае пользователь может указать, что определенное правило имеет более высокий приоритет (давая ему большее число), чем другие правила.В этом случае правило с более высокой значимостью будет предпочтительным.Приоритеты LIFO основаны на назначенном значении счетчика «Действие рабочей памяти», причем все правила, созданные во время одного и того же действия, получают одно и то же значение.Порядок выполнения набора срабатываний с одинаковым значением приоритета является произвольным.
Но выполнение моих двух правил с 5 объектами для каждого типа дает странные результаты - На некоторых объектах выполняется правило с выражением 1раньше, чем правило с выделением 10. Если я удаляю обновление из правила, сначала выполняются правила с выделением 10, и только затем с выделением 1.
package com.sample
import com.sample.DroolsTest.Message;
import com.sample.DroolsTest.Message2;
rule "Hello World2"
salience 10
when
m : Message()
m2 : Message2(status <0)
then
System.out.println( "Second Rule With Salience 10");
System.out.println( "m status = "+m.getStatus());
System.out.println( "m2 status = "+m2.getStatus());
m2.setStatus(m2.getStatus()*(-1));
update(m2);
end
rule "Hello World3"
salience 1
when
m2 : Message2()
m : Message()
then
System.out.println( "Third Rule With Salience 1");
System.out.println( "m status = "+m.getStatus());
System.out.println( "m2 status = "+m2.getStatus());
end
rule "GoodBye"
salience 0
when
eval(true)
then
System.out.println( "End" );
end
А вот код Java, который поможет вам быстрее его протестировать
package com.sample;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderErrors;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.logger.KnowledgeRuntimeLogger;
import org.drools.logger.KnowledgeRuntimeLoggerFactory;
import org.drools.runtime.StatefulKnowledgeSession;
/**
* This is a sample class to launch a rule.
*/
public class DroolsTest {
public static final void main(String[] args) {
try {
// load up the knowledge base
KnowledgeBase kbase = readKnowledgeBase();
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
// go !
System.out.println("Start");
for(int i=0; i<5; i++){
Message message = new Message(i);
ksession.insert(message);
Message2 message2 = new Message2(-i);
ksession.insert(message2);
}
ksession.fireAllRules();
logger.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
private static KnowledgeBase readKnowledgeBase() throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("Sample.drl"), ResourceType.DRL);
KnowledgeBuilderErrors errors = kbuilder.getErrors();
if (errors.size() > 0) {
for (KnowledgeBuilderError error: errors) {
System.err.println(error);
}
throw new IllegalArgumentException("Could not parse knowledge.");
}
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
return kbase;
}
public static class Message {
private int status;
public int getStatus() {
return this.status;
}
public Message(int status) {
super();
this.status = status;
}
public void setStatus(int status) {
this.status = status;
}
}
public static class Message2 {
private int status;
public Message2(int status) {
this.status = status;
}
public int getStatus() {
return this.status;
}
public void setStatus(int status) {
this.status = status;
}
}
}
Спасибо, я очень ценю вашу помощь.PS: я знаю, что полагаться на последовательность применения правил - не очень хорошая идея, но прежде чем я начал работать над этим, мне показалось, что это заслуживает доверия.