Skip to content

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

Open
@ninjulkar

Description

@ninjulkar

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions