Порядок правил Drools при изменении фактических данных - PullRequest
0 голосов
/ 07 марта 2019

Я новичок в Drools и либо неправильно понимаю, что может делать Drools, либо мне что-то не хватает.

У меня есть простой класс Fact

public class MeterReadTO {

private String status = "";

public String getStatus() {
  return status;
}

public void setStatus(String status) {
   this.status = status;
}

public boolean isInvalid() {
  return status.equals("invalid");
};

}

С правилами

 rule "Rule Invalid"

 dialect "mvel"
 when
     MeterReadTO( isInvalid());
 then
  System.out.println("Rule Invalid Fired");

end

rule "Rule Not Invalid"

 dialect "mvel"
when
   not MeterReadTO(  isInvalid());
then
   System.out.println("Rule Not Invalid Fired");

end

rule "Set Status"

 dialect "mvel"
 when
    $mr: MeterReadTO()
  then
      System.out.println("Rule Set Status Fires");

     modify($mr) {
      setStatus("invalid")
     }
   end

и я запускаю правила с

@RunWith(SpringRunner.class)
@SpringBootTest
public class Dependancy {


static KieSession ksession;

Logger logger = LoggerFactory.getLogger(Dependancy.class);


MeterReadTO mr;


@BeforeClass
public static void start() {


      KieContainer kieClasspathContainer = KieServices.Factory.get().getKieClasspathContainer();
        ksession = kieClasspathContainer.newKieSession("DependancyTest");
}

@Test
public void contextLoadsAndRetrievesData() {

    MeterReadTO mr = new MeterReadTO();
    mr.setId(50);

    ksession.insert(mr);

    // when
    ksession.fireAllRules();
    ksession.dispose();

    // Then
    System.out.println("After Drools, status is " + mr.getStatus());

}

}

, и я получаю результат

Rule Not Invalid Fired
Rule Set Status Fires
After Drools, status is invalid

Используя сеанс с сохранением состояния, я ожидалсм. пожар «Недействительное правило» после срабатывания «Правило Set Status».Если я переместлю правило Set Status из нижней части списка правил в верхнюю, то я получу

Rule Set Status Fires
Rule Not Invalid Fired
After Drools, status is invalid

Так что Drools явно не знает об изменении статуса в правиле Set Status.Чего мне не хватает?

С уважением

СЛЕДУЙТЕ ЗА.

Теперь я действительно запутался.Если я удалю вызов метода isInvalid () в моем файле правил и вместо этого буду ссылаться на метод getStatus (), чтобы правила теперь выглядели как

rule "Rule Invalid"

dialect "mvel"
when
  MeterReadTO( getStatus() == "ïnvalid");
then
  System.out.println("Rule Invalid Fired");

end

rule "Rule Not Invalid"

 dialect "mvel"
 when
   MeterReadTO( getStatus() == "");
 then
    System.out.println("Rule Not Invalid Fired");

end

rule "Set Status"

dialect "mvel"

when
    $mr: MeterReadTO()
  then
      System.out.println("Rule Set Status Fires");

  modify($mr) {
    setStatus("ïnvalid")
  }

   end

, то я получаю вывод, который ожидал

Rule Not Invalid Fired
Rule Set Status Fires
Rule Invalid Fired
After Drools, status is ïnvalid  

Кто-нибудь может объяснить, что происходит?

1 Ответ

0 голосов
/ 08 марта 2019

По сути, Drools не может понять, что когда вы изменяете status вашего факта, это влияет на результат метода isInvalid().

Когда вы изменяете факт, Drools постарается свести к минимуму переоценку правил в максимально возможной степени. В вашем случае Drools не может установить связь между методами setStatus() и isInvalid().

Во втором случае вы используете в своих правилах метод getStatus(), а затем Drools может устанавливать соединения (с помощью простых соглашений именования POJO).

Одним из способов убедиться, что Drools понимает связь между setStatus() и isInvalid(), может быть использование аннотации @watch в вашем правиле:

rule "Rule Invalid"
 dialect "mvel"
 when
   MeterReadTO( isInvalid()) @watch(status)
 then
  System.out.println("Rule Invalid Fired");
end

rule "Rule Not Invalid"
dialect "mvel"
when
  not MeterReadTO(  isInvalid()) @watch(status)
then
  System.out.println("Rule Not Invalid Fired");
end

Проблема этого подхода заключается в том, что ваши правила действительно привязаны к вашей модели. Если способ, которым вы проверяете, является ли факт недействительным, и который необходимо изменить, чтобы задействовать больше полей, вы должны следовать правилу, изменяя правило @watch.

Другим решением было бы отметить отношение в самой модели, используя аннотацию @Modifies:

public class MeterReadTO {
  private String status = "";

  public String getStatus() {
    return status;
  }

  @Modifies( { "invalid" } )
  public void setStatus(String status) {
    this.status = status;
  }

  public boolean isInvalid() {
    return status.equals("invalid");
  };

}

Вы можете найти больше информации по этой теме в Официальной документации Drools .

Надеюсь, это поможет,

...