deliveredtechnologies / rulebook

100% Java, Lambda Enabled, Lightweight Rules Engine with a Simple and Intuitive DSL
http://www.deliveredtechnologies.com
Apache License 2.0
716 stars 124 forks source link

Question regard ERROR_ON_FAILURE #163

Open Tamir-Schwarz opened 5 years ago

Tamir-Schwarz commented 5 years ago

Hi, I am trying to set rule to throw exception on failure, i followed the documentation but it seems the rule still gets it default CONTINUE_ON_FAILURE.

I tried to debug it, on the when phase the GoldenRule is created again, but this time with the default RuleChainActionType (_CONTINUE_ONFAILURE) instead of my parameter. I think the issue is originated on class RuleBuilder line 246

Sample code:

    @Test
    public void test(){
        // Arrange

        // build rule 1
        String defaultResult = "";
        Rule<String, String> rule_1 = RuleBuilder.create(GoldenRule.class, RuleChainActionType.ERROR_ON_FAILURE)
                .withName("rule_1")
                .withFactType(String.class)
                .withResultType(String.class)
                .then(x -> {throw new RuntimeException("ERROR");})
                .build();

        // build rule 2
        Rule<String, String> rule_2 = RuleBuilder.create(GoldenRule.class, RuleChainActionType.ERROR_ON_FAILURE)
                .withName("rule_2")
                .withFactType(String.class)
                .withResultType(String.class)
                .then((fact, result) -> result.setValue(result.getValue().concat("_B")))
                .build();

        // Build rulebook
        RuleBook<String> ruleBook = RuleBookBuilder.create()
                .withResultType(String.class)
                .withDefaultResult(defaultResult)
                .addRule(rule_1)
                .addRule(rule_2)
                .build();

        // Build fact
        NameValueReferableMap factMap = new FactMap();
        factMap.setValue("key", "value");

        // Act
        ruleBook.run(factMap);

        // Assert
        Optional<Result<String>> result = ruleBook.getResult();
        System.out.println(result);
        String value = result.get().getValue();
        assertTrue(value.equals(defaultResult));
    }

As far as i understand, this test should pass, but it fails due to the fact that the error is not thrown and not stops the evaluation chain.

Did i missed something?

Thanks in advance, Tamir.

egorkarimov commented 2 years ago

There is a bug. Solved by extending GoldenRule and redefining default constructor:

public class ErrorOnFailureGoldenRule<T, U> extends GoldenRule<T, U> {
        public ErrorOnFailureRule(Class<T> factType) {
            super(factType, RuleChainActionType.ERROR_ON_FAILURE);
        }
 }

Then use it instead of GoldenRule class in the builder:

RuleBuilder.create(ErrorOnFailureGoldenRule.class)
                .withFactType(Facts.class)
                .withResultType(Result.class);