【问题标题】:How to use variables in easy rules?如何在简单规则中使用变量?
【发布时间】:2020-08-20 22:08:12
【问题描述】:

我正在使用JSON descriptor 加载使用easy-rules 的规则,并且我想在简单规则actions 中使用变量。例如,我有一组规则,我在其中定义规则 ID、名称、描述,如下所示

[
  {
    "id": 1,
    "name": "Task using Oracle DB",
    "description": "Updated comments to update connector",
    "priority": 1,
    "condition": "user.getTaskData().getTargetConnectorType().contains(\"Oracle\") || user.getTaskData().getSourceConnectorType().contains(\"Oracle\")",
    "actions": [
      "user.setRuleDetail([\"impacted_feature\":\"Task using Oracle DB\", \"desc\": \"Updated comments to update connector\", \"impact\":\"low\", \"count\":\"Using \"+user.getTaskDetail().getConnBucketData().get(\"Oracle\")+\" connector type\",\"id\":1, \"extra_detail\":\"{\\\"impacted_connectors\\\":[\\\"Oracle\\\"]}\"]);"
    ]
  }
]

这里有以下两件事吗

-> 使用规则 name, description 内部操作?

...
[
  {
    "id": 1,
    "name": "Task using Oracle DB",
    "description": "Updated comments to update connector",
    "priority": 1,
    "condition": "user.getTaskData().getTargetConnectorType().contains(\"Oracle\") || user.getTaskData().getSourceConnectorType().contains(\"Oracle\")",
    "actions": [
      "user.setRuleDetail([\"impacted_feature\":\"+name+\", \"desc\": \"+description+\", \"impact\":\"low\", \"count\":\"Using \"+user.getTaskDetail().getConnBucketData().get(\"Oracle\")+\" connector type\",\"id\":1, \"extra_detail\":\"{\\\"impacted_connectors\\\":[\\\"Oracle\\\"]}\"]);"
    ]
  }
]
...

-> 在actions下使用变量?

...
"actions": [
        "def name = \"Task using Oracle DB\"",
        "def desc = \"Updated comments to update connector\"",
        "def connector = \"Oracle\"",           
      "user.setRuleDetail([\"impacted_feature\":\"+name+\", \"desc\": \"+desc+\", \"impact\":\"low\", \"count\":\"Using \"+user.getTaskDetail().getConnBucketData().get(\"Oracle\")+\" connector type\",\"id\":1, \"extra_detail\":\"{\\\"impacted_connectors\\\":[\\\"Oracle\\\"]}\"]);"
    ]
...

更新 这里我正在初始化MVELRuleFactory

def computeRules(UserData userData) {
    try {
        Facts facts = new Facts()
        facts.put("user", userData)

        MVELRuleFactory ruleFactory = new MVELRuleFactory(new JsonRuleDefinitionReader())
        Rules rules = ruleFactory.createRules(new FileReader("conf/rules.json"))

        //create a default rules engine and fire rules on known facts
        RulesEngine rulesEngine = new DefaultRulesEngine()
        rulesEngine.fire(rules, facts)
    } catch(FileNotFoundException fnfe) {
        _errorLogger.error("Error in #computeRules {}", fnfe)
    } catch(Exception e) {
        _errorLogger.error("Error in #computeRules {}", e)
    }
    return userData.getRuleDetail()
}

//UserData POJO

@CompileStatic
class UserData {
    String orgKey
    TaskData taskData
    List<Map> ruleDetail

    UserData(String orgKey, TaskData taskData) {
        this.orgKey = orgKey
        this.taskData = taskData
    }

    String getOrgKey() {
        return orgKey
    }

    void setOrgKey(String orgKey) {
        this.orgKey = orgKey
    }

    TaskData getTaskData() {
        return taskData
    }

    void setTaskData(TaskData taskData) {
        this.taskData = taskData
    }

    List<Map> getRuleDetail() {
        return ruleDetail
    }

    void setRuleDetail(Map ruleData) {
        if (this.ruleDetail == null)
            this.ruleDetail = []
        this.ruleDetail.add(ruleData)
    }

    @Override
    public String toString() {
        return "UserData{" +
                "orgKey='" + orgKey + '\'' +
                ", taskData=" + taskData +
                ", ruleDetail=" + ruleDetail +
                '}';
    }
}

【问题讨论】:

  • java & groovy 标签在这里做什么?
  • @daggett easy rules 是一个 Java 规则引擎,动作内部的代码是用 groovy 编写的
  • 据我所知github.com/j-easy/easy-rules 不包含常规的操作实现。
  • @daggett 抱歉,我的操作使用了 expression language support 的 java 代码,我的项目在 groovy 中,它同时使用了 java 和 groovy。
  • 请编辑您的问题并提供至少部分代码 - 您如何初始化 SpELRuleFactory

标签: java groovy rule-engine easy-rules


【解决方案1】:

您基本上是在尝试访问条件/操作中的规则信息,或者换句话说,让条件/操作了解规则。您可以使用规则侦听器来做到这一点,该侦听器将规则作为事实放在规则执行之前,然后将其删除。这是一个简单的例子:

public class MyListener implements RuleListener {
    @Override
    public void beforeExecute(Rule rule, Facts facts) {
        facts.put("rule", rule);
    }

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

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

    // implement other methods if needed
}

这里是如何使用它:给定以下规则描述文件rule-aware-action.json

[
  {
    "name": "rule aware action",
    "description": "a rule where the action is aware of the rule",
    "condition": "true",
    "actions": [
      "System.out.println(rule.name);"
    ]
  }
]

以下示例打印rule aware action

import java.io.FileReader;

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.MVELRuleFactory;
import org.jeasy.rules.support.reader.JsonRuleDefinitionReader;

public class RuleAwareActionExample {

    public static void main(String[] args) throws Exception {
        MVELRuleFactory mvelRuleFactory = new MVELRuleFactory(new JsonRuleDefinitionReader());
        Rules rules = mvelRuleFactory.createRules(new FileReader("rule-aware-action.json"));
        DefaultRulesEngine rulesEngine = new DefaultRulesEngine();
        rulesEngine.registerRuleListener(new MyListener());
        Facts facts = new Facts();
        rulesEngine.fire(rules, facts);
    }
}

这意味着该操作能够访问它所属的规则的名称。该示例展示了如何让操作了解其规则,但它也应该适用于条件。

【讨论】:

    【解决方案2】:

    总结一下,不是和是的!

    要了解如何,您必须了解,只要变量以 Fact 的形式存在或以某种方式存在于 MVEL 上下文中,就可以解决它。

    这里有详细的答案-

    在操作中使用规则namedescription

    没有。您不能在Action 中使用Rulenamedescription。要在规则中使用外部变量,您必须将它们添加为事实。如果您想要这种能力,请使用drools,它功能丰富框架。

    在操作下使用变量?

    这是你可以做到的,但不是你现在的方式。 defMVEL 中具有特殊含义。因此,要使用变量,您可以执行以下任一操作-

    1. 将变量定义为单独的操作项:

      "actions": [
         "name=\"....\"",
         "description=\"....\"",
         "user.setRuleDetail([\"impacted_feature\": name, \"desc\": description, \"impact\": \"low\", \"count\":\"Using \"+user.getTaskDetail().getConnBucketData().get(\"Oracle\")+\" connector type\",\"id\":1, \"extra_detail\":\"{\\\"impacted_connectors\\\":[\\\"Oracle\\\"]}\"]);"
      ]
      
    2. 添加内联变量:

      "actions": [
         "name=\"....\";description=\"....\";user.setRuleDetail([\"impacted_feature\": name, \"desc\": description, \"impact\": \"low\", \"count\":\"Using \"+user.getTaskDetail().getConnBucketData().get(\"Oracle\")+\" connector type\",\"id\":1, \"extra_detail\":\"{\\\"impacted_connectors\\\":[\\\"Oracle\\\"]}\"]);"
      ]
      

      注意在操作中使用它们时您不需要额外的quotes

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2017-04-01
      • 1970-01-01
      • 2013-09-17
      • 1970-01-01
      • 2013-03-03
      • 2020-03-23
      • 1970-01-01
      • 2013-04-25
      • 2010-10-20
      相关资源
      最近更新 更多