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

RuleBuilder doesn't create a Rule with action type RuleChainActionType.ERROR_ON_FAILURE #208

Open chandmanish opened 2 years ago

chandmanish commented 2 years ago

I was expecting by using RuleBuilder.create(GoldenRule.class, RuleChainActionType.ERROR_ON_FAILURE) I an create a Rule which will throw RuleException in case of a error while executing the rule. But it didn't work and when I investigate it in detail I found that RuleBuilder will never create a Rule with RuleChainActionType.ERROR_ON_FAILURE action.

In my understanding the private method private Rule<T, U> newRule() creates a new instance of the Rule. in this method a Rule with a RuleChainActionType is instantiated only in the first condition when action type is STOP_ON_FAILURE (line 168 of RuleBuilder). there is no other place where the Rule is created with RuleChainActionType as second parameter.

I saw that at line 176 of the RuleBuilder the second parameter in the constructor is resultType return (Rule)constructor.newInstance(this._factType, this._resultType); But the GoldenRule class doesn't have a constructor for this combination.

Can this be a bug , actionType should be passed as second parameter instead of resultType

mchevvuri commented 2 years ago

I'm facing the exact same issue, it doesn't matter whether I'm setting this in rulebookbuiler or rulebuilder. GolenRule class has a logic where it checks if action type is "STOP_ONFAILURE" and then constructs it. I guess it shouldn't have that "IF" conditon and it should just proceed with creating construction using action type.

kzander91 commented 2 years ago

Just encountered the same issue. Looks like ERROR_ON_FAILURE currently only works when defining Rules with annotated POJOs using @Rule(ruleChainAction = RuleChainActionType.ERROR_ON_FAILURE). Quite a deal-breaker for me. I'm currently working around this by post-processing all my rules and setting the private _actionType field using reflection.

I'm using Spring and all my rules are beans, so I can do it like this:

@Bean
static BeanPostProcessor errorOnFailureGoldenRulePostProcessor() {
    Field actionTypeField = FieldUtils.getField(GoldenRule.class, "_actionType");
    ReflectionUtils.makeAccessible(actionTypeField);
    return new BeanPostProcessor() {

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) {
            if (bean instanceof GoldenRule<?, ?> goldenRule) {
                ReflectionUtils.setField(actionTypeField, goldenRule, RuleChainActionType.ERROR_ON_FAILURE);
            }
            return bean;
        }
    };
}

This will of course only work if you need all rules to use this action type.