j-easy / easy-rules

The simple, stupid rules engine for Java
https://github.com/j-easy/easy-rules/wiki
MIT License
4.91k stars 1.06k forks source link

facts.put not working in MVELRule? #321

Closed alexweirig closed 3 years ago

alexweirig commented 3 years ago

Hello,

I' trying to use easy-rules based on what I read in the wiki and the faqs.

LoginValidationState is a simple ENUM.

I have a very basic test case: ParserConfiguration parserConfiguration = new ParserConfiguration(); parserConfiguration.addImport(LoginValidationState.class); ParserContext parserContext = new ParserContext(parserConfiguration); MVELRule x = new MVELRule(parserContext) .name("a") .description("a") .priority(1) .when("true") .then("facts.put(\"result\", LoginValidationState.VOTER_HAS_PROCUREMENT);") ; rules.register(x);

RulesListenerImpl rulesListenerImpl = new RulesListenerImpl();

    DefaultRulesEngine rulesEngine = new DefaultRulesEngine(new RulesEngineParameters().skipOnFirstAppliedRule(true));
    rulesEngine.registerRuleListener(rulesListenerImpl);
    rulesEngine.fire(rules, facts);

With my listener in place, I get the following output: result ----> OK evaluationResult = true rule = a 1 = [Error: unresolvable property or identifier: facts] [Near : {... facts.put("result", LoginValid ....}] ^ [Line: 1, Column: 1]

So how can I put a value for "result" in the facts in my rule?

From what I read in the faq and other places (gitter) I expected this to work?

Many thanks in advance

Alex

fmbenhassine commented 3 years ago

This is because you are referring to a fact named facts in your expression which does not exist. If you want to access the map of facts like that, you can add the entire facts map as a fact using a listener. Here is a quick example:

import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rule;
import org.jeasy.rules.api.RuleListener;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.core.DefaultRulesEngine;
import org.jeasy.rules.mvel.MVELRule;

public class Launcher {

    public static void main(String[] args) {
        Facts facts = new Facts();
        Rules rules = new Rules();
        MVELRule x = new MVELRule()
                .when("true")
                .then("facts.put(\"result\", \"foobar\");");
        rules.register(x);

        DefaultRulesEngine rulesEngine = new DefaultRulesEngine();
        rulesEngine.registerRuleListener(new RuleListener() {
            @Override
            public void beforeExecute(Rule rule, Facts facts) {
                facts.put("facts", facts);
            }

            @Override
            public void onSuccess(Rule rule, Facts facts) {
                facts.remove("facts");
            }

            @Override
            public void onFailure(Rule rule, Facts facts, Exception exception) {
                facts.remove("facts");
            }
        });
        rulesEngine.fire(rules, facts);

        System.out.println("facts = " + facts); // prints: facts = [Fact{name='result', value=foobar}]
    }
}

This is actually similar to #240 but for facts instead of rules.

I'm closing this issue for now, but feel free to add a comment if you need more help on this.

alexweirig commented 3 years ago

Thank you very much for the clarification. That helps.