hyperjumptech/grule-rule-engine

Missing field in JSON fact should not result in error while evaluating when and then of rule

ninjulkar opened this issue · 1 comments

Describe the bug
When JSON fact is used, and when has some condition on a field which is missing in JSON, rule should consider that condition unmatched instead of erroring out entire execution.
If my condition is Event.Username == "john" || Event.Surname == "doe", if Event does not have Username field the execution fails with error like

got left hand expression error. got left hand expression error. got json field 'Username' is undefined" lib=grule-rule-engine package=ast

Instead here, it should consider Event.Username == "john" as false and evaluate Event.Surname == "doe" and match if it is true.

To Reproduce
Steps to reproduce the behavior:

  1. I create code for this and that
rule Rule_90  "MatchingEquals1" salience 1 {
	when
	Event.Username == "john" || Event.Surname == "doe"
	then
	Output.Matched(Event.Surname, Event.Surname);
	Retract("Rule_90");
	Complete();
}
  1. With a test for this and that
package benchmark_grule_engine

import (
	"encoding/json"
	"fmt"
	"github.com/hyperjumptech/grule-rule-engine/ast"
	"github.com/hyperjumptech/grule-rule-engine/builder"
	"github.com/hyperjumptech/grule-rule-engine/engine"
	"github.com/hyperjumptech/grule-rule-engine/pkg"
	"testing"
)

var jsonRule = `rule Rule_90  "MatchingEquals1" salience 1 {
	when
	Event.Username == "john" || Event.Surname == "doe"
	then
	Output.Matched(Event.Surname, Event.Surname);
	Retract("Rule_90");
	Complete();
}`

func TestMissingJsonField(t *testing.T) {
	kl, err := buildKnowledgeLibrary(jsonRule)
	if err != nil {
		t.Error("Failed to add rule")
	}
	eng := engine.NewGruleEngine()

	kb := kl.NewKnowledgeBaseInstance("MyRules", "v1.0")
	ev := JsonEvent{Surname: "doe"}
	dc := ast.NewDataContext()
	j, err := json.Marshal(ev)
	if err != nil {
		panic(err)
	}
	o := Output{}
	err = dc.AddJSON("Event", j)
	if err != nil {
		panic(err)
	}
	err = dc.Add("Output", &o)
	if err != nil {
		panic(err)
	}

	err = eng.Execute(dc, kb)
	if err != nil {
		panic(err)
	}
	fmt.Println("Exec done....")

}

type JsonEvent struct {
	Username string `json:"Username,omitempty"`
	Surname  string `json:"Surname,omitempty"`
}

type Output struct {
}

func (receiver Output) Matched(username string, surname string) {
	fmt.Println("Matched", username, surname)
}

func buildKnowledgeLibrary(ruleQuery string) (*ast.KnowledgeLibrary, error) {
	kl := ast.NewKnowledgeLibrary()
	rb := builder.NewRuleBuilder(kl)
	ruleDef := pkg.NewBytesResource([]byte(ruleQuery))
	err := rb.BuildRuleFromResource("MyRules", "v1.0", ruleDef)
	return kl, err
}
  1. Instead of seeng this
    Matching the rule

  2. I see that
    Error while evaluating rule Rule_90, got left hand expression error. got left hand expression error. got json field 'Username' is undefined" lib=grule-rule-engine package=ast time="2024-01-04T13:46:04+05:30

Expected behavior
Rule should match as next OR expression matches without error.

Additional context
It also fails if we are using missing field in then as well.

@newm4n any plans to fix this ?