Понимание группы
Я попробовал пример, чтобы посмотреть, как работает группа участников. Вначале я поставил фокус ksession в группу "ag1" и уволил правила.
package com.sample
import com.sample.DroolsTest.Message;
rule "Hello World"
agenda-group "ag1"
when
m : Message( status == Message.HELLO, myMessage : message )
then
System.out.println( "Hello World" );
m.setMessage( "Goodbye cruel world" );
m.setStatus( Message.GOODBYE );
update( m );
end
rule "Hello World 2"
agenda-group "ag2"
when
m : Message( status == Message.HELLO, myMessage : message )
then
System.out.println( "Hello World 2" );
m.setMessage( "Goodbye cruel world" );
m.setStatus( Message.GOODBYE );
update( m );
end
rule "GoodBye"
agenda-group "ag1"
when
m : Message( status == Message.GOODBYE, myMessage : message )
then
System.out.println( "GoodBye" );
drools.setFocus("ag2");
System.out.println("comeon man");
m.setStatus(com.sample.DroolsTest.Message.HELLO);
update(m);
end
rule "GoodBye 2"
agenda-group "ag2"
when
Message( status == Message.GOODBYE, myMessage : message )
then
System.out.println( "GoodBye 2" );
end
Это результат, который я получил.
Hello World
GoodBye
comeon man
Hello World 2
GoodBye 2
GoodBye
comeon man
Hello World 2
GoodBye 2
GoodBye
comeon man
Hello World 2
GoodBye 2
GoodBye
comeon man
Hello World 2
GoodBye 2
GoodBye
comeon man
Hello World 2
...
...
Я мог понять первые 5 строк вывода до "GoodBye 2". Но поскольку фокус был установлен на "ag2", как он вернулся к правилу "ag1" группы "ag1" и, следовательно, был рекурсирован.
Спасибо.
Ответы
Ответ 1
Повествовательные группы работают как стек. Когда вы устанавливаете фокус на данную группу, эта группа помещается поверх стека. Когда движок пытается запустить следующую активацию и больше нет активации в данной группе, эта группа удаляется из верхней части стека, а группа под ней снова получает фокус.
Итак, это похоже на это (основная группа по умолчанию всегда присутствует):
* STACK: [MAIN, ag1]
Hello Word fires and activates both "GoodBye" rules
GoodBye fires, activates both "Hello World" rules and sets the focus to "ag2"
* STACK: [MAIN, ag1, ag2]
Hellow World 2 fires, cancels the "Hello World 1" rule and activates both "GoodBye" rules
GoodBye 2 fires because ag2 has the focus
* There are no more activations in ag2 to fire, so ag2 is removed from the stack
* STACK: [MAIN, ag1]
* The "GoodBye" rule is still active in ag1, so it fires
GoodBye fires, activates both "Hello World" rules and sets the focus to "ag2"
* STACK: [MAIN, ag1, ag2]
Hellow World 2 fires, cancels the "Hello World 1" rule and activates both "GoodBye" rules
...
И цикл повторяется.
Такое поведение очень легко увидеть, если вы используете журнал аудита в Eclipse IDE.
Надеюсь, что это поможет.
Ответ 2
Поскольку вы изменили факты в сеансе (ваш объект сообщения находится в ваших фактах, которые, как я думаю) во время вычисления правила, другие правила вычисляются снова, не зависящие от группы участников, к которой они принадлежат, для обновления Drools база знаний.
Вы можете добавить no-loop true
, чтобы предотвратить это в строке после rule
definition
Я не уверен, но это поведение, которое я заметил в своем приложении, и должен так разрешить ваш бесконечный цикл. Кстати, логично снова вычислить правила, когда факты меняются.