j-easy / easy-rules

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

Unable to get a list of rules annotated with @Rule #353

Open arunav-bhattacharya opened 3 years ago

arunav-bhattacharya commented 3 years ago

@benas - First of all I want to thank you for this awesome project. However, I want to bring up a concern that I m facing to fetch a list of rules in a List when annotated with @Rule.

I want to execute a set of Rules based on a particular attribute in the input request. I have the attribute and the corresponding rules configured in a JSON object. At application start-up, I want to create a map of the possible values of the attributes and the corresponding instances of Rule object, but I m unable to do so when the rules are defined using @Rule annotation. I m using Instance to get a list of Rule, but it is unable to identify the type. However, instead of using @Rule annotation, when these rule classes implement the Rule interface, it is able to fetch the Rules in a list using Instance.

But instead of implementing the Rule interface, I want to define my rules with @Rule annotation and fetch it in a list - can you please help me with this.

PFB my sample code in Kotlin -

import org.jeasy.rules.annotation.Action
import org.jeasy.rules.annotation.Condition
import javax.enterprise.inject.Instance
import org.jeasy.rules.annotation.Rule
import org.jeasy.rules.api.Fact
import org.jeasy.rules.api.Facts
import javax.inject.Inject
import javax.enterprise.context.ApplicationScoped

class Sample (@Inject val rules: Instance<org.jeasy.rules.api.Rule>){
    fun process(){
        rules.forEach { println("rules=${it.name}") }    
    }
}

@Rule(name="Rule1")
@ApplicationScoped
object Rule1{
    @Condition
    fun `when`(facts: Facts) = true
    @Action
    fun then(facts: Facts) = facts.add(Fact("Rule1", true))
}

@Rule(name="Rule2")
@ApplicationScoped
object Rule2{
    @Condition
    fun `when`(facts: Facts) = false
    @Action
    fun then(facts: Facts) = facts.add(Fact("Rule2", true))
}

In addition to the above, I tried using Reflection as well to fetch the @Rule annotated classes in a list. I fetched the Class references with AnnotatedType as org.jeasy.rules.annotation.Rule and then tried casting this Class to org.jeasy.rules.api.Rule which was throwing a ClassCastException. Maybe I m doing something incorrectly here, as I m not sure how to obtain instances of org.jeasy.rules.api.Rule from AnnotatedTypes as org.jeasy.rules.annotation.Rule.

Thanks, Arunav