Search code examples
drools

Drools problem, why drools see just my first rule?


I need help with drools. Problem is that when I run an application (which is otherwise done in the spring) and when I try to fire all rules, only the first rule starts and the other rules cannot be started.

This is a my drl file with some my 3 rules.

    package drools.medicine

import com.example.demo.model.Pacijent;
import com.example.demo.model.Lek;
import com.example.demo.model.SastojakLeka;
import com.example.demo.model.Pregled;
import com.example.demo.model.ValidacijaDiagnoze;
import java.util.List;
import java.util.Set;
import java.util.HashSet;



rule "test-rule"
   agenda-group "alergija"
   when
       $vd: ValidacijaDiagnoze()
   then
       System.out.println("TEEEST!!!");
end



rule "Alergic-on-medicine"
    agenda-group "alergija"
    when
        $v: ValidacijaDiagnoze()
        $pregled: Pregled($prepisaniLek: prepisanLek)
        $lek: Lek() from $prepisaniLek
        $pacijent: Pacijent(alergicanNaLek($lek))
    then
        System.out.println("Pacijent je alergican na lek: "+ $lek.getNazivLeka());
        modify( $v ){
            setValid(false),
            setMessage("PATIENT IS ALLERGIC!")
        }
end


rule "Alergic-on-ingredient"
    agenda-group "alergija"
    lock-on-active
    when
        $v: ValidacijaDiagnoze()
        $pregled: Pregled($prepisaniLek: prepisanLek)
        $lek: Lek($sastojci: sastojak) from $prepisaniLek
        $sastojak: SastojakLeka() from $sastojci
        $pacijent: Pacijent(alergicanNaSastojak($sastojak))
    then
        System.out.println("Pacijent je alergican na sastojak " + $sastojak.getNazivSastojka());
        modify( $v ){
            setValid(false),
            setMessage("PATIENT IS ALLERGIC ON INGREDIENT!")
        }
end

Below is where i call the kieSession to fire all rules.

// Take medicine(and ingredient) and decide throw rules are they ok or not.
    @CrossOrigin(origins = "http://localhost:3000")
    @PostMapping(value = "/validation")
    public ResponseEntity<?> validateDiagnosis(@RequestBody PregledDto pregledDto){

        //TO DO--   
        KieSession kieSession = kieContainer.getKieBase("MedicineBase").newKieSession();


        //initial state, witch can be changed in rules if patient is allergic
        ValidacijaDiagnoze vd = new ValidacijaDiagnoze();
        vd.setMessage("PATIENT IS NOT ALLERGIC");
        vd.setValid(true);


        FactHandle fact;
        fact =  kieSession.insert(vd);
        kieSession.getAgenda().getAgendaGroup("alergija").setFocus();
        System.out.println("Number of fired rules: "+ kieSession.fireAllRules()); // 1
        kieSession.dispose();

        return new ResponseEntity<>(vd, HttpStatus.OK);

    }

And there is my kmodule file in META-INF folder.

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <kbase name="DiagnosisBase" packages="drools.diagnosis">
        <ksession name="diagnosis" />
    </kbase>

    <kbase name="DiagnosisBase2" packages="drools.diagnosis2">
        <ksession name="diagnosis2" />
    </kbase>

    <kbase name="MedicineBase" packages="drools.medicine">
        <ksession name="medicine" />
    </kbase>

</kmodule>

Result in eclipse console.

Help me to solve problem I am new in using drools.

Also let me know where I am making mistakes and what are the best practices when using drools, thank you very much.


Solution

  • The number returned by the method kieSession.fireAllRules() is the number of rules that actually matched and were executed by the Drools engine. If a rule's left hand side (the 'when' clause) does not match the inputs, it does not match, and it will not be executed.

    In the example rules given, the test rule checks only for the presence of a ValidacijaDiagnoze in working memory. The other two rules require that the ValidacijaDiagnoze includes children (a Lek instance or SastojakLeka instance) as well as an instance of Pacijent also in working memory.

    However, in the code that fires the rules, only a ValidacijaDiagnoze is added to the working memory like this:

    ValidacijaDiagnoze vd = new ValidacijaDiagnoze();
    vd.setMessage("PATIENT IS NOT ALLERGIC");
    vd.setValid(true);
    

    Since this instance has no Lek or SastojakLeka associated with, it won't trigger the other rules. Additionally, since there is no Pacijent in the working memory, those other rules won't trigger either.

    Therefore, since only the first rule can trigger, fireAllRules returns 1 because that is the number of rules that actually executed.