Search code examples
javajsonjacksondroolsjsonnode

How to compare nested JsonNode field values with Java object parameter values in DROOLS?


I've been trying to execute a set of rules on a request object on the basis of some set of configuration value. Below is the example on what I am trying to do:

Configuration: config.json

{
  "company1": {
    "site1": {
      "maxWeeklyWorkingHours": 40,
      "rule2": [1, 3, 4],
    },
    "site2": {
      "maxWeeklyWorkingHours": 40,
      "rule2": [1, 3, 4],
    }
  },
  "company2": {
    "site1": {
      "maxWeeklyWorkingHours": 40,
      "rule2": [1, 3, 4],
    },
    "site2": {
      "maxWeeklyWorkingHours": 40,
      "rule2": [1, 3, 4],
    }
  }
}

Request Class Object: policyDataToBeVerified

PolicyDataToBeVerified(company=company1, site=site1, workerWeeklyWorkingHours=39, isRequestValid=0)

I converted the config.json into a JsonNode object:configJson and passed both policyDataToBeVerified and configJson to drools working memory. Below are the approaches I tried to take to frame the rule but failed anyways:

APPROACH 1: drools.drl

rule "maxWorkingHours"
when
    $configJson: JsonNode()
    $policyData: PolicyDataToBeVerified(maximumWeeklyWorkingHours <= $configJson.get(company).get(site).get("workerWeeklyWorkingHours"))
then
    $policyData.setIsRequestValid(true)
 end

Issue: I am getting null pointer exception at $configJson.get(company).get(site).get("workerWeeklyWorkingHours")

APPROACH 2: I even tried to use configJSON as a global variable but, then drools didn't allow me to use get methods of JsonNode to get the nested fields from JSON


I've been trying to find a solution to my problem for past few days, but nothing worked. I'd be happy to learn even if we can view this problem from a different perspective and solve it in a different way, or if we can debug this, whatever works.


Solution

  • NOTE: IntellijIDEA has inaccurate linting for .drl files, so request you to not rely on it.

    I created a validateSlotsResponse as following for better handling of response:

    package com.example.demo;
    import lombok.Builder;
    import lombok.Data;
    import java.util.List;
    
    @Data
    @Builder
    public class ValidateSlotsResponse {
        boolean isRequestValid;
        List<String> comments;
    }
    

    I'll pass this class's object into the working memory of DROOLS, and will update it inside the drools program, which will then be used as the respose for validation.

    Below are the rules inside my drools file, please make sure you have made the right imports:

    rule "fetchMaximumAllowedWeeklyWorkingHours"
    when
         $validateSlotsResponse: ValidateSlotsResponse()
         $policyDataToBeVerified: PolicyDataToBeVerified()
         $configJson: JsonNode()
         $workingHoursAllowed:Integer() from $configJson.get($policyDataToBeVerified.getCompany()).get($policyDataToBeVerified.getSite()).get("maxWeeklyWorkingHours").intValue()
    then
     end
    
    
     rule "maxWorkingHoursAccept" extends "fetchMaximumAllowedWeeklyWorkingHours"
     when
         eval($policyDataToBeVerified.workerWeeklyWorkingHours() <= $workingHoursAllowed)
     then
         $policyDataToBeVerified.setIsRequestValid(true);
         $validateSlotsResponse.setRequestValid(true);
         $validateSlotsResponse.setComments(new ArrayList<>(Arrays.asList("Worker allowed to work for "+$policyDataToBeVerified.getMaximumWeeklyWorkingHours() + " hours")));
      end
    
    
      rule "maxWorkingHoursReject" extends "fetchMaximumAllowedWeeklyWorkingHours"
      when
           eval($policyDataToBeVerified.workerWeeklyWorkingHours() > Integer.parseInt($workingHoursAllowed.toString()))
      then
           $policyDataToBeVerified.setIsRequestValid(false);
           $validateSlotsResponse.setRequestValid(false);
           $validateSlotsResponse.setComments(new ArrayList<>(Arrays.asList("Worker not allowed to work more than "+ $workingHoursAllowed + " hours")));
      end