Получение некоторого события от Drools, когда факт больше не соответствует

Пожалуйста, взгляните на две настройки кода ниже.

Настройка 1:

public class DroolsAnotherTest {
    private static KieSession kSession;
    private static Building building;
    private static FactHandle buildingFact;
    public static final void main(String[] args) {
        try {
            // load up the knowledge base
            KieServices ks = KieServices.Factory.get();
            KieContainer kContainer = ks.getKieClasspathContainer();
            kSession = kContainer.newKieSession("ksession-rules");
            building = new Building();
            building.setRooms(2);
            buildingFact = kSession.insert(building);
            kSession.fireAllRules();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    public static void fireAgain(){
        System.out.println("inside fireAgain method");
        kSession.fireAllRules(); // firing the rules second time
    }
public static class Building {

        public int rooms;
        public int getRooms() {
            return this.rooms;
        }
        public void setRooms(int rooms) {
            this.rooms = rooms;
        }
    }
}

И файл .drl

package com.sample

import com.sample.DroolsAnotherTest.Building;
import com.sample.DroolsAnotherTest;

rule "Building"
    when
        Building( rooms <3 )
    then
        System.out.println( "Building rule fired" );
        DroolsAnotherTest.firingAgain();
end

После запуска вывод: правило построения запущено.

внутри метода fireAgain


Настройка 2: здесь я просто изменил метод fireAgain() на:

public static void fireAgain(){
                System.out.println("inside fireAgain method");
        kSession.delete(buildingFact);
        building.setRooms(4);
        kSession.insert(building);
        kSession.fireAllRules(); // firing the rule second time
}

все остальное такое же. После запуска вывод снова тот же: сработало правило построения.

внутри метода fireAgain


В моем понимании,

в настройке 1 правило не сработало второй раз, потому что факт не изменился в рабочей памяти.

в настройке 2 правило не сработало во второй раз, потому что теперь факт обновился и не соответствует условию правила.

Мой вопрос: генерирует ли Drools какое-либо событие для настройки 2 (правило срабатывает один раз, но теперь не срабатывает снова, потому что факт обновлен?) Таким образом, я могу различать: правило не сработало, потому что факт не изменился < strong>и его не уволили, потому что теперь факт не соответствует условию правила?


person fellow_dev    schedule 18.08.2017    source источник


Ответы (1)


Невозможно определить, почему правило не включено в повестку дня.

Вы знаете, когда вы обновляете факт, поэтому, если это интересно по какой-то причине, зарегистрируйте его в факте или где-либо еще.

И НЕ, повторяю: НЕ звоните fireAllRules, пока другой такой вызов в том же сеансе все еще выполняется. Возможны всевозможные неожиданные эффекты.

person laune    schedule 18.08.2017
comment
Спасибо @laune. Немного грустно обнаружить, что Drools не предлагает ничего подобного. В AgendaEventListener есть метод matchCancelled (событие MatchCancelledEvent), но я понятия не имею, когда это событие генерируется. Можете ли вы пролить свет на это? - person fellow_dev; 18.08.2017
comment
Привет @laune, не могли бы вы помочь мне подробно разобраться в последней части вашего ответа? «Могут быть всевозможные неожиданные эффекты». ! Любой пример или статья, обсуждающая эту проблему? - person fellow_dev; 19.08.2017
comment
Вам удалось сделать рекурсивный вызов метода, который не предназначен для рекурсивного вызова. Данные в стеке должны быть в безопасности, но нет гарантии, что все объекты в сеансе и вокруг него (например, повестка дня) не затронуты злоупотреблением. Если нужно активировать больше правил, они все равно будут запущены, без повторного вызова fireAllRules. - person laune; 22.08.2017
comment
Понятно. На самом деле мой вариант использования состоит в том, чтобы сначала проверить правило, затем выполнить некоторое обновление (которое выполняется каким-то другим модулем), а затем продолжить проверку, могу ли я применить дальнейшее правило и обновить снова, пока не возникнет ситуация, когда больше не может быть правил. применяться. Есть ли лучший способ добиться этого, чем то, что я делаю? Заранее спасибо. - person fellow_dev; 23.08.2017
comment
Ну... Идея состоит в том, чтобы позволить движку работать в сеансе с отслеживанием состояния, пока правила больше не срабатывают. Обновления можно выполнять без перезапуска работающего двигателя. - person laune; 23.08.2017