Search code examples
drools

Drools rules logic not working as expected


Hierarchy:
If any employee is paid 100k, Organization.maxSalary = 100k.
If any employee is paid 50k, Organization.maxSalary = 50k if no one else receives 100k.

DRL

rule "Salary 100000"
    when
        $org: Organization()
        $empDetail: EmployeeDetail() from $org.employeeDetail
        $employee: Employee( $org.maxSalary != 100000,
                             salary == 100000
                           ) from $empDetail.employees
    then
        System.out.println("Salary 100000: " + $org.maxSalary);
        $org.maxSalary = 100000;
end

rule "Salary 50000"
    when
        $org: Organization()
        $empDetail: EmployeeDetail() from $org.employeeDetail
        $employee: Employee( $org.maxSalary != 100000
                          && $org.maxSalary != 50000,
                             salary == 50000
                           ) from $empDetail.milestoneDetails
    then
        System.out.println("Salary 50000: " + $org.maxSalary);
        $org.maxSalary = 50000;
end

Input JSON 1:

{
  "Organization": {
    "EmployeeDetail": {
      "Employees" : [
        {
          "name": "willie"
          "salary": "50000",
        },
        {
          "name": "john"
          "salary": "100000",
        },
        {
          "name": "jack"
          "salary": "50000",
        },
        {
          "name": "jim"
          "salary": "50000",
        }
      ]
    }
  }
}

Expected console output: Salary 100000: null

Actual console output: Salary 100000: null

All good.

Input JSON 2:

{
  "Organization": {
    "EmployeeDetail": {
      "Employees" : [
        {
          "name": "willie"
          "salary": "50000",
        },
        {
          "name": "jack"
          "salary": "50000",
        },
        {
          "name": "jim"
          "salary": "50000",
        }
      ]
    }
  }
}

Expected console output: Salary 50000: null

Actual console output:

Salary 50000: null
Salary 50000: 50000
Salary 50000: 50000

In both cases, the JSON result is good with Organization.maxSalary set correctly. But why is the console output weird?


Solution

  • You want to fire the rule by checking the org.maxSalary. However you should not check the $org.maxSalary from inside the Employee object, as this is not an Eployee's property but Orgranization's.

    Also, after setting the maxSalary on org, you should update the Organization fact with the new value (maxSalary). update() makes the rules engine aware that a fact has been modified.

    Here is the complete rules code

    rule "Salary 100000"
        when
            $org: Organization(maxSalary != 100000)
            $empDetail: EmployeeDetail() from $org.employeeDetail
            $employee: Employee( salary == 100000
                               ) from $empDetail.employees
        then
            System.out.println("Salary 100000: " + $org.maxSalary);
            $org.maxSalary = 100000;
            update($org);
    end
    
    rule "Salary 50000"
        when
            $org: Organization(maxSalary != 100000 && maxSalary != 50000)
            $empDetail: EmployeeDetail() from $org.employeeDetail
            $employee: Employee(
                                 salary == 50000
                               ) from $empDetail.employees
        then
            System.out.println("Salary 50000: " + $org.maxSalary);
            $org.maxSalary = 50000;
            update($org);
    
    end
    

    Output on the Json2 is

    Salary 50000: null
    

    I also do not understand the logic of having

     System.out.println("Salary 50000: " + $org.maxSalary);
     $org.maxSalary = 50000;
    

    instead of

     $org.maxSalary = 50000;
     System.out.println("Salary 50000: " + $org.maxSalary);
    

    It seems weird to first print an empty maxSalary and then assign the amount to maxSalary.