2016-09-30 35 views
0

我想執行一個非常基本的例子,演示如何使用Drools的accumulate()函數,但得到了一個java.lang.NullPointerException異常。Drools的空指針異常accumulate()

下面是代碼:

Metric.java:

package com.sample; 

public class Metric 
{ 
    public String id; 
    public double value; 

    public Metric(String id, double value) 
    { 
    this.id = id; 
    this.value = value; 
    } 
} 

ruleFile1.drl:

package com.sample 

declare Metric 
    @role(event) 
end 

rule "rule1" 
when 
    Metric() 
    metricAverage: Number() from accumulate(
     Metric($value : value), 
     average($value)) 
then 
    System.out.println("metric value average " + metricAverage); 
end 

KSessionGenerator.java:

package com.sample; 

import java.io.FileInputStream; 
import java.io.FileNotFoundException; 

import org.kie.api.KieBase; 
import org.kie.api.KieBaseConfiguration; 
import org.kie.api.KieServices; 
import org.kie.api.builder.KieBuilder; 
import org.kie.api.builder.KieFileSystem; 
import org.kie.api.builder.Message; 
import org.kie.api.builder.Results; 
import org.kie.api.conf.EventProcessingOption; 
import org.kie.api.runtime.KieContainer; 
import org.kie.api.runtime.KieSession; 

public class KSessionGenerator { 

    public KieSession buildKSession(String ruleFilePath){ 
    KieServices kieServices = KieServices.Factory.get(); 

    FileInputStream fis = null; 
    try { 
     fis = new FileInputStream(ruleFilePath); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
     return null; 
    } 

    String virtualRuleFilePath = "src/main/resources/ruleFile1.drl"; 
    KieFileSystem kfs = kieServices.newKieFileSystem(); 
    kfs.write(virtualRuleFilePath, kieServices.getResources().newInputStreamResource(fis)); 

    KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll(); 
    Results results = kieBuilder.getResults(); 
    if (results.hasMessages(Message.Level.ERROR)) { 
     System.out.println(results.getMessages()); 
     throw new IllegalStateException("### errors ###"); 
    } 

    KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId()); 

    // Change the engine mode to 'stream' 
    KieBaseConfiguration config = kieServices.newKieBaseConfiguration(); 
    config.setOption(EventProcessingOption.STREAM); 

    KieBase kieBase = kieContainer.newKieBase(config); 
    KieSession kSession = kieBase.newKieSession(); 

    return kSession; 
    } 
} 

DroolsTest1.java:

package com.sample; 

import org.kie.api.runtime.KieSession; 

public class DroolsTest1 { 

    public static final void main(String[] args) { 
    try { 
     String ruleFilePath = "src/main/resources/rules/ruleFile1.drl"; 
     KieSession kSession = (new KSessionGenerator()).buildKSession(ruleFilePath); 

     // go ! 
     Metric metric1 = new Metric("m1", 50); 
     Metric metric2 = new Metric("m2", 60); 

     kSession.insert(metric1); 
     kSession.insert(metric2); 

     System.out.println("Firing all rules ..."); 
     kSession.fireAllRules(); 
     System.out.println("Rules fired!"); 

     System.out.println("Bye"); 
    } catch (Throwable t) { 
     t.printStackTrace(); 
    } 
    } 
} 

kmodule.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> 
    <kbase name="rules" packages="rules"> 
     <ksession name="ksession-rules"/> 
    </kbase> 
</kmodule> 

異常的完整堆棧跟蹤:

Firing all rules ... 
java.lang.RuntimeException: java.lang.NullPointerException 
    at org.drools.core.rule.SingleAccumulate.accumulate(SingleAccumulate.java:90) 
    at org.drools.core.phreak.PhreakAccumulateNode.addMatch(PhreakAccumulateNode.java:759) 
    at org.drools.core.phreak.PhreakAccumulateNode.doLeftInserts(PhreakAccumulateNode.java:163) 
    at org.drools.core.phreak.PhreakAccumulateNode.doNode(PhreakAccumulateNode.java:80) 
    at org.drools.core.phreak.RuleNetworkEvaluator.switchOnDoBetaNode(RuleNetworkEvaluator.java:562) 
    at org.drools.core.phreak.RuleNetworkEvaluator.evalBetaNode(RuleNetworkEvaluator.java:533) 
    at org.drools.core.phreak.RuleNetworkEvaluator.innerEval(RuleNetworkEvaluator.java:334) 
    at org.drools.core.phreak.RuleNetworkEvaluator.outerEval(RuleNetworkEvaluator.java:161) 
    at org.drools.core.phreak.RuleNetworkEvaluator.evaluateNetwork(RuleNetworkEvaluator.java:116) 
    at org.drools.core.phreak.RuleExecutor.reEvaluateNetwork(RuleExecutor.java:235) 
    at org.drools.core.phreak.RuleExecutor.evaluateNetworkAndFire(RuleExecutor.java:106) 
    at org.drools.core.common.DefaultAgenda.fireNextItem(DefaultAgenda.java:1016) 
    at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1302) 
    at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1289) 
    at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1262) 
    at com.sample.DroolsTest1.main(DroolsTest1.java:20) 
Caused by: java.lang.NullPointerException 
    at org.drools.core.rule.Declaration.getValue(Declaration.java:228) 
    at com.sample.Rule_rule11017979978AccumulateExpression0Invoker.evaluate(Rule_rule11017979978AccumulateExpression0Invoker.java:19) 
    at org.drools.core.base.accumulators.JavaAccumulatorFunctionExecutor.accumulate(JavaAccumulatorFunctionExecutor.java:109) 
    at org.drools.core.rule.SingleAccumulate.accumulate(SingleAccumulate.java:82) 
    ... 15 more 

我使用Drools的版本6.2.0最終通過插件基於Eclipse 4.5.2火星

誰能告訴我該錯誤的原因有它的解決方案一起?

+0

的可能的複製[什麼是空指針異常,怎麼解決呢?(http://stackoverflow.com/questions/218384/what-is-a-nullpointerexception執行-and-how-do-i-fix-it) – Raedwald

+1

@Rededwald這是這個問題的重複嗎? –

+1

@Raedwald:我覺得OP是心知肚明的NPE是什麼,這個問題針對一個特定的,非平凡的情況下,看到我的回答如下。恕我直言,這絕對不是你鏈接的一般問題的重複 – hammerfest

回答

3

試過代碼,所述NPE由

"$value" -> "Method threw 'java.lang.NullPointerException' exception. 
Cannot evaluate org.drools.core.rule.Declaration.toString()" 

這是由於不具有用於它的字段中的任何getter方法公制類引起的。添加getter和代碼不會有任何問題

+0

這解決了錯誤。但我不明白如何?爲什麼獲得者的存在會影響規則的執行?無論如何,類屬性是公開的。另外,你提到的錯誤 - '無法計算org.drools.core.rule.Declaration.toString()「'不存在於我的問題寫的堆棧跟蹤你是怎麼得到這個 –

+1

堆棧跟蹤包括org.drools? .core.rule.Declaration.getValue(Declaration.java:228)。把一個斷點這個方法,你會看到包裹錯誤調試器。類領域是公衆並不一定意味着它們是處理可見的框架引擎,這往往是通過吸氣只工作,使用反射。我沒有檢查它在關於Drools的更詳細,但在過去的其他框架中遇到了類似的問題。使用私人領域和公共getter方法通常是一個很好的做法。 – hammerfest