question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Problem with ScopedParams and null values

See original GitHub issue

Hi,

I use RulesEngine, version 4.0.0 with .NET Core 3.1.

I have a bunch of rules that I simplified using GlobalParams and LocalParams.

The problem I have is that my params refer to array properties of a child object, but, in some situations, this child object may be null. When this occurs, the whole workflow breaks down instead of returning valid values. I would like to know what would be the best practice in that situation.

Here is an example of the input data, the rules I use and the output I get… Please note that I have simplified everything to the smallest meaningful sample… Our real-life objects are much more complex and I have lots of rules, so reusing logic with GlobalParams and LocalParams is a life saver!

Input object:

{
    "ActivityId": 1,
    "Description": "Activity Description",
    "Quote": {
        "QuoteId": 1234,
        "Items": [{
                "ItemId": 1,
                "Description": "Product 1",
                "Quantity": 2,
                "UnitPrice": 1.00
            },
            {
                "ItemId": 2,
                "Description": "Product 2",
                "Quantity": 1,
                "UnitPrice": 10.00
            },
        ]
    }
}

Here is the workflow I use:

[
    {
        "WorkflowName": "Workflow",
        "WorkflowRulesToInject": null,
        "GlobalParams": [
            {
                "Name": "PiecesCount",
                "Expression": "Activity.Quote == null ? 0d : Activity.Quote.Items.Sum(Quantity)"
            }
        ],
        "Rules": [
            {
                "RuleName": "Load/unload pieces",
                "Operator": null,
                "ErrorMessage": "Rule failed",
                "RuleExpressionType": "LambdaExpression",
                "Expression": "PiecesCount != 0",
                "Actions": {
                    "OnSuccess": {
                        "Name": "OutputExpression",
                        "Context": {
                            "Expression": "PiecesCount * 90d"
                        }
                    }
                },
                "Rules": null
            }
        ]
    }
]

For completeness sake, here is how the workflow is run. The rules variable holds my workflow and the activity variable holds my input data…

var rulesEngine = new RulesEngine.RulesEngine(rules, new ReSettings()
{
    CustomTypes = null,
});

var result = await rulesEngine.ExecuteAllRulesAsync("Workflow",
                                                    new RuleParameter("Activity", activity));

When I run this workflow with the sample object provided, The PiecesCount is 3 and the OutputExpression is 270d, as expected.

In some cases, my “activities” have no Quote, like so:

{
    "ActivityId": 1,
    "Description": "Activity Description",
    "Quote": null
}

In that case, I have this error message when the Rule is run:

Error while compiling rule Load/unload pieces: No applicable method ‘Sum’ exists in type ‘Object’, in ScopedParam: PiecesCount

I would expect the rule to return 0d, since Activity.Quote == null (as a reminder, the GlobalParam’s expression is Activity.Quote == null ? 0d : Activity.Quote.Items.Sum(Quantity)), but it seems the RulesEngine has interpreted the whole expression and failed because the Quote is null.

If my workflow has many rules and some rules never refer to my GlobalParam, all rules fail, even those who don’t refer the param…

For instance, all rules of this workflow fail with the same error message:

[
    {
        "WorkflowName": "Workflow",
        "WorkflowRulesToInject": null,
        "GlobalParams": [
            {
                "Name": "PiecesCount",
                "Expression": "Activity.Quote == null ? 0d : Activity.Quote.Items.Sum(Quantity)"
            }
        ],
        "Rules": [
            {
                "RuleName": "Load/unload pieces",
                "Operator": null,
                "ErrorMessage": "Rule failed",
                "RuleExpressionType": "LambdaExpression",
                "Expression": "PiecesCount != 0",
                "Actions": {
                    "OnSuccess": {
                        "Name": "OutputExpression",
                        "Context": {
                            "Expression": "PiecesCount * 90d"
                        }
                    }
                },
                "Rule": null
            },
            {
                "RuleName": "Other unrelated rule",
                "Operator": null,
                "ErrorMessage": "Rule failed",
                "RuleExpressionType": "LambdaExpression",
                "Expression": "true == true",
                "Actions": {
                    "OnSuccess": {
                        "Name": "OutputExpression",
                        "Context": {
                            "Expression": "10d"
                        }
                    }
                },
                "Rules": null
            }
        ]
    }
]

Here is the complete response:

[
  {
    "Rule": {
      "RuleName": "Load/unload pieces",
      "Properties": null,
      "Operator": null,
      "ErrorMessage": "Rule failed",
      "Enabled": true,
      "RuleExpressionType": "LambdaExpression",
      "WorkflowsToInject": null,
      "Rules": null,
      "LocalParams": null,
      "Expression": "PiecesCount != 0",
      "Actions": {
        "OnSuccess": {
          "Name": "OutputExpression",
          "Context": {
            "Expression": "PiecesCount * 90d"
          }
        },
        "OnFailure": null
      },
      "SuccessEvent": null
    },
    "IsSuccess": false,
    "ChildResults": null,
    "Inputs": {
      "Activity": {
        "ActivityId": 1,
        "Description": "Activity Description",
        "Quote": null
      }
    },
    "ActionResult": {
      "Output": null,
      "Exception": null
    },
    "ExceptionMessage": "Error while compiling rule `Load/unload pieces`: No applicable method 'Sum' exists in type 'Object', in ScopedParam: PiecesCount"
  },
  {
    "Rule": {
      "RuleName": "Other unrelated rule",
      "Properties": null,
      "Operator": null,
      "ErrorMessage": "Rule failed",
      "Enabled": true,
      "RuleExpressionType": "LambdaExpression",
      "WorkflowsToInject": null,
      "Rules": null,
      "LocalParams": null,
      "Expression": "true == true",
      "Actions": {
        "OnSuccess": {
          "Name": "OutputExpression",
          "Context": {
            "Expression": "10d"
          }
        },
        "OnFailure": null
      },
      "SuccessEvent": null
    },
    "IsSuccess": false,
    "ChildResults": null,
    "Inputs": {
      "Activity": {
        "ActivityId": 1,
        "Description": "Activity Description",
        "Quote": null
      }
    },
    "ActionResult": {
      "Output": null,
      "Exception": null
    },
    "ExceptionMessage": "Error while compiling rule `Other unrelated rule`: No applicable method 'Sum' exists in type 'Object', in ScopedParam: PiecesCount"
  }
]

Any help / workaround will be much appreciated!

Thanks in advance!

Best regards!

Issue Analytics

  • State:closed
  • Created 5 months ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
ghigadcommented, May 2, 2023

Hi @abbasc52,

A quick follow-up…

I went through my tests again and found out that my test program was using an ExpandoObject.

I updated my test to use a strongly typed object and my basic rules worked!

I’ll rerun through my monster rules and make sure they use strongly typed objects and see if I still face the issue.

I’ll keep you posted of my results.

Thank you again for your help!

Best regards!

0reactions
ghigadcommented, May 19, 2023

Hi @abbasc52,

Sorry for the delay…

Using strongly typed objects solved my issue!

Thank you for your help!

Best regards!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Data is Null. This method or property cannot be called on ...
So I deleted NULL values from databases and every request worked fine after that. As far as I understood, an error occurs because...
Read more >
database design - Why shouldn't we allow NULLs?
I think the question is poorly phrased, as the wording implies that you've already decided NULLs are bad. Perhaps you meant "Should we...
Read more >
Working with SQL NULL values
This article will show functions and operators for handling SQL NULL values.
Read more >
We Need to Stop Using null: Here's Why | by Arindam Roy
The fundamental problem of null is that it is trying to represent the fact that it is not a value while being assigned...
Read more >
6 Tips for Dealing With Null Values
In this article, we will work on how to handle null values. First, there will be some very simple methods and slowly we...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found