如标题I所述,我想在我的Drools项目中更改冲突解决方案。我在此site
上找到了以下代码段ConflictResolver[] conflictResolvers =
new ConflictResolver[] { SalienceConflictResolver.getInstance( ),
FifoConflictResolver.getInstance( ) };
RuleBase ruleBase = java.io.RuleBaseLoader( url, CompositeConflitResolver( conflictResolver));
但是它缺少信息放在哪里以及sholud是url
参数。
提前感谢您的帮助。
答案 0 :(得分:1)
正如文件所说:
Drools 4.0支持自定义冲突解决策略;而这个 它还没有暴露在Drools中 最终用户通过Drools 5.0中的knowledge-api。 http://docs.jboss.org/drools/release/5.2.0.Final/drools-expert-docs/html/ch04.html
因此,如果你使用Drools 5+,你将无法改变冲突解决方案除非你做一些反思魔术。冲突解决程序在StatefulKnowledgeSession对象的Agenda对象中结算。您可以通过使用调试器(它是Agenda对象的内容)来看到这一点:
要替换ConflictResolver,首先需要StatefulKnowledgeSession的实例(在以下代码段中将是ksession)。然后,您需要提取一些嵌套的私有字段,然后您可以使用例如 RandomConflictResolver 的实例替换字段值。完整代码:
Agenda agenda = ksession.getAgenda();
Field agendaField = agenda.getClass().getDeclaredField("agenda");
agendaField.setAccessible(true);
Object agendaObject = agendaField.get(agenda);
Field mainField = agendaObject.getClass().getDeclaredField("main");
mainField.setAccessible(true);
Object mainObject = mainField.get(agendaObject);
Field queueField = mainObject.getClass().getDeclaredField("queue");
queueField.setAccessible(true);
Object queueObject = queueField.get(mainObject);
Field comparatorField = queueObject.getClass().getDeclaredField("comparator");
comparatorField.setAccessible(true);
Object comparator = comparatorField.get(queueObject);
ConflictResolver randomResolver = org.drools.conflict.RandomConflictResolver.getInstance();
comparatorField.set(queueObject, randomResolver);
基于:documentation和调试器会话。
答案 1 :(得分:0)
为了证明解雇顺序不会影响整体结果我会使用AgendaFilter。我正在使用6.x草绘轮廓,但是这个API自5.x以来没有改变。
KieBase kieBase = ...;
Collection<KiePackage> packages = kieBase.getKiePackages();
List<Rule> rules = new ArrayList<>();
for( KiePackage p: packages ){
rules.addAll( p.getRules() );
}
现在你有了所有的规则。构建这个接受单个规则的简单过滤器:
class Selector implements AgendaFilter {
List<Rule> rules;
int ruleIndex;
Selector( List<Rule> rules ){
this.rules = rules;
}
void setRuleIndex( int value ){ this.ruleIndex = value; }
int getRulesSize(){ return rules.size(); }
boolean accept(Match match){
return match.getRule().equals( rules.get( ruleIndex ) );
}
}
实例化:
Selector selector = newSelector( rules );
您现在可以执行所有已激活的规则(但请参见下文):
for( int i = 0; i < selector.getRulesSize(); ++i ){
int fired = kieSession.fireAllRules( selector, i );
}
0..size-1的任何其他排列可能会产生另一个发射序列。您可以针对少数规则系统地执行此操作,或者您可以使用一些随机排列。
更有效的测试将跟踪第一次运行中传递给过滤器的Match数据,并仅将这些数据用于连续执行。
警告到目前为止概述的方法不考虑工作记忆中的更改。当某些规则 n + k 被触发时,可能会激活规则 n 。如果您确实更改了工作记忆,则必须
do {
int sumf = 0;
for( int i : somePermutation ){
int fired = kieSession.fireAllRules( selector, i );
sumf += fired;
}
} while( sumf > 0 );
我从未做过这样的测试。似乎通过依赖规则发射的固有顺序来获得正确的结果是非常罕见的,与此订单中获得各种错误结果相反。
注意规则触发顺序的其他排列是可以通过更改DRL(或其包中的)规则的顺序或通过将事实插入的顺序更改为工作内存来实现的。对于某些情况,即使这样也可以提供足够的测试用例来显示您的意图。