javaspring-bootdroolsruleskie

how to execute 2 drool rules in Java with different logic having dependency between them, used ruleflow-group but 2nd rule not getting executed


I am trying to execute different drool rules in java having different business logic but rule 2 needs to be executed after rule 1 gets executed. For this, I have used ruleflow-group. I am able to execute rule 1 properly but rule 2 is return 0 from kieSession.fireAllRules() method.

My 2nd drool rule looks like below now:

import com.drools.A;
import com.drools.B;
import java.util.List;
import java.util.ArrayList;
import com.drools.OutputDTO;
global List<OutputDTO> outputDTOs;


rule "ABC with Approved Status"
    ruleflow-group "status"
        when
            $outputDTO: OutputDTO();
            $transaction: A( $b : b != null )
              exists( B( group == "ABC" , status == "Approved" )  from $b )           
        then         
            $outputDTO.setGroup("ABC");
            $outputDTO.setStatus("Approved");
            outputDTOs.add($outputDTO);
        end;

rule "XYZ with Approved Status"
    ruleflow-group "status"
    when
        $outputDTO: OutputDTO();
        $transaction: A( $b : b != null )
                      exists( B( group == "XYZ" , status == "Approved" )  from $b )     
    then      
         $outputDTO.setGroup("XYZ");
         $outputDTO.setStatus("Approved");
         outputDTOs.add($outputDTO);
    end;

The rule execution part is as below:

            kieSession.getAgenda().getAgendaGroup("scope").setFocus();
            int x = kieSession.fireAllRules(); // rule 1 got executed here successfully
            logger.debug("Number of rules matched for getting dynamic scopes - {} ", x); // x=3

            //processing from rule 1 data and creating object A and then trying to //execute rule 2 from below
           
          
            List<OutputDTO> outputDTOs = new ArrayList<>();
            kieSession.setGlobal("outputDTOs", outputDTOs);
            kieSession.insert(a); // A object
            kieSession.getAgenda().getAgendaGroup("status").setFocus();
           int y = kieSession.fireAllRules();  // getting y =0 here
            kieSession.dispose();
            return outputDTOs;

Can anyone please tell me how can I run rule 2 here ?


Solution

  • You've not really described what your use case is, but given your attempt, this is what I interpret you want to do:

    1. Rule 1 should trigger if A contains at least 1 B which has group "ABC" and status "approved".
    2. Rule 2 should trigger if A contains at least 1 B which has group "XYZ" and status "approved".

    I further presume the following:

    Your rules would, therefore, look like this:

    rule "Rule 1"
    when
      A( $bList: b != null )
      exists( B( group == "ABC", status == "approved" ) from $bList )
    then
      //...
    end
    
    rule "Rule 2"
    when
      A( $bList: b != null )
      exists( B( group == "XYZ", status == "approved") from $bList )
    then
      // ...
    end
    

    In both rules, the first thing we do is extract the sub-list of B's if it is not null. Then we check that there exists at least one B instance which meets your criteria. Since you don't actually do anything with this B instance, we can use the exists operation to simply check for its presence.

    If you actually do need to do something with the B instance, you'd assign it to a variable rather than using exists:

    rule "Rule 1 with captured B"
    when
      A( $bList: b != null )
      $b: B(group == "ABC", status == "approved") from $bList
    then
      // can reference $b here
    end
    

    Note that this version may trigger multiple times if there are multiple B present which meet your criteria.