java.lang.RuntimeException: неожиданный глобальный [результат]

У меня есть этот класс, который читает файлы правил, вставляет факты и запускает правила.

public class RuleRunner {

    private KieServices kieServices = KieServices.Factory.get();

    public enum RuleType {
        XLS,
        DRL;
    }

    private void prepareSession(String ruleResource, RuleType type) {
        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
        Resource resource = kieServices.getResources().newClassPathResource(ruleResource);
        switch(type) {
        case XLS: {
            resource.setResourceType(ResourceType.DTABLE);
            break;
        }
        case DRL: {
            resource.setResourceType(ResourceType.DRL);
            break;
        }
        }
        kieFileSystem.write(resource);

        KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
        kieBuilder.buildAll();
        if (hasErrors(kieBuilder)) {
            System.out.println("Failed to build!");
            return;
        }
    }

    private boolean hasErrors(KieBuilder builder) {
        if (builder.getResults().getMessages().size() > 0) {
            return true;
        }
        return false;
    }

    public void runRules(Object[] facts, GlobalVariable[] variables, String ruleResource, RuleType type) {
        prepareSession(ruleResource, type);

        KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
        KieSession kieSession = kieContainer.newKieSession();
        for (GlobalVariable variable: variables) {
            kieSession.setGlobal(variable.getVariableName(), variable);
        }
        for(Object fact: facts) {
            kieSession.insert(fact);
        }
        kieSession.fireAllRules();

        kieSession.dispose();
    }
}

И у меня есть это правило

package com.pack.drools.apps;

import com.pack.drools.apps.domain.Person;
import com.pack.drools.apps.domain.GlobalVariable;

global GlobalVariable result

rule "if person has less that 10 cash then hes poor"
when
    $person:Person(cash < 10)
then
    result.setResult(-1);
end

rule "if person has more than 90 cash then hes rich"
when
    $person:Person(cash > 90)
then
    result.setResult(-2);
end

rule "if person has more than 10 and less than 90 then hes average"
when
    $person:Person(cash >= 10 && cash <= 90)
then
    result.setResult(-3);
end

Однако когда я пытаюсь запустить свое приложение

package pack.rup.drools.apps;

import pack.rup.drools.apps.core.RuleRunner;
import pack.rup.drools.apps.core.RuleRunner.RuleType;
import pack.rup.drools.apps.domain.GlobalVariable;
import pack.rup.drools.apps.domain.Person;


public class Main {

    private static final String DEFAULT_PACKAGE = "pack/rup/drools/apps/";
    private static final String XLS_FILE = DEFAULT_PACKAGE + "rule.xls";
    private static final String DRL_FILE = DEFAULT_PACKAGE + "rule.drl";

    public static void main(String[] args) {
        RuleRunner ruleRunner = new RuleRunner();

        // build fact
        Person person = new Person();
        person.setName("John");
        person.setCash(100);

        GlobalVariable result = new GlobalVariable();
        result.setVariableName("result");

//        ruleRunner.runRules(new Object[] { person }, new GlobalVariable[] { result }, XLS_FILE, RuleType.XLS);
        ruleRunner.runRules(new Object[] { person }, new GlobalVariable[] { result }, DRL_FILE, RuleType.DRL);

        System.out.println("Rule result: " + result.getResult());
    }
}

мой журнал выглядит так

10:13:00.974 [main] INFO  o.d.c.k.b.impl.KieRepositoryImpl - KieModule was added: MemoryKieModule[releaseId=org.default:arti
fact:1.0.0-SNAPSHOT]
10:13:00.982 [main] INFO  o.d.c.k.b.impl.ClasspathKieProject - Found kmodule: file:/D:/workTestProjects/simpleDroolsApps/sda
-core/build/resources/main/META-INF/kmodule.xml
10:13:00.982 [main] DEBUG o.d.c.k.b.impl.ClasspathKieProject - KieModule URL type=file url=/D:/workTestProjects/simpleDrools
Apps/sda-core/build/resources/main
10:13:01.026 [main] WARN  o.d.c.k.b.impl.ClasspathKieProject - Unable to find pom.properties in /D:/workTestProjects/simpleD
roolsApps/sda-core/build/resources/main
10:13:01.027 [main] WARN  o.d.c.k.b.impl.ClasspathKieProject - As folder project tried to fall back to pom.xml, but could no
t find one for null
10:13:01.027 [main] WARN  o.d.c.k.b.impl.ClasspathKieProject - Unable to load pom.properties from/D:/workTestProjects/simple
DroolsApps/sda-core/build/resources/main
10:13:01.027 [main] WARN  o.d.c.k.b.impl.ClasspathKieProject - Cannot find maven pom properties for this project. Using the
container's default ReleaseId
10:13:01.027 [main] DEBUG o.d.c.k.b.impl.ClasspathKieProject - Discovered classpath module org.default:artifact:1.0.0-SNAPSH
OT
10:13:01.028 [main] INFO  o.d.c.k.b.impl.KieRepositoryImpl - KieModule was added: FileKieModule[releaseId=org.default:artifa
ct:1.0.0-SNAPSHOT,file=D:\workTestProjects\simpleDroolsApps\sda-core\build\resources\main]
10:13:01.035 [main] WARN  o.d.c.k.b.impl.AbstractKieModule - No files found for KieBase defaultKieBase, searching folder D:\
workTestProjects\simpleDroolsApps\sda-core\build\resources\main
10:13:01.131 [main] DEBUG o.drools.core.impl.KnowledgeBaseImpl - Starting Engine in PHREAK mode
Exception in thread "main" java.lang.RuntimeException: Unexpected global [result]
        at org.drools.core.impl.StatefulKnowledgeSessionImpl.setGlobal(StatefulKnowledgeSessionImpl.java:1163)
        at pack.rup.drools.apps.core.RuleRunner.runRules(RuleRunner.java:57)
        at pack.rup.drools.apps.Main.main(Main.java:27)
:sda-core:run FAILED

person lapots    schedule 20.10.2015    source источник


Ответы (3)


Кажется, что вы должны использовать определенный каталог при записи ресурсов DRL или XLS в KieFileSystem. Пытаться

String filename = ...; // code that set filename to (e.g.) rule.drl
kieFileSystem.write( "src/main/resources/" + filename, resource );

Также в вашем ДХО есть

import com.pack.drools.apps.domain....

тогда как в Main.java есть

import pack.rup.drools.apps.domain....

Этот импорт должен быть из одного пакета.

Изменить. Чтобы проверить, какие глобальные объекты находятся в сеансе:

Globals globals = kieSession.getGlobals();
System.out.println( globals.getGlobalKeys() );
person laune    schedule 20.10.2015
comment
При отладке я обнаружил, что он не работает в строке kieSession.setGlobal(variable.getVariableName(), variable); - person lapots; 21.10.2015
comment
@ user1432980 Конечно. Вы получите эту ошибку, если используете имя переменной, которое не соответствует ни одному из глобальных объектов в DRL, что обязательно произойдет, если у вас есть пустой сеанс, то есть один без глобальных переменных и правил, из-за того, что не сохранены ресурсы ) правильно. - Вы последовали моим предложениям? - person laune; 21.10.2015
comment
да. Проблема с пакетами - это просто тип, потому что я изменил ее для вопроса. И указание пути куда писать не помогло. - person lapots; 21.10.2015
comment
Хорошо, поэтому, пожалуйста, добавьте пару строк в свой код, прежде чем пытаться установить, и сообщите мне о выходе. - person laune; 21.10.2015
comment
Собственно вопрос решен. Я скопировал ваш путь - src/main/resource, но на самом деле я храню xls в подпакетах этого файла, и когда я его указал, он начал работать нормально! src/main/resources/com/pack/drools/apps. - person lapots; 21.10.2015

Мы потратили 2 дня с моим коллегой и наконец выяснили, что «Неожиданная глобальная» ошибка возникает, когда ваш DRL пуст из-за ошибок компиляции, поэтому addGlobal () не может найти никакого глобального объявления.

Как только компилятор DRL не генерирует никаких исключений при ошибках, вы можете проверить это самостоятельно, используя:

if (kieBuilder.hasErrors()) {
    System.out.print( kieBuilder.getErrors() );
}
person antonpinchuk    schedule 11.07.2019

Если вы вставляете глобал, вы должны его использовать. Например, если у вас есть:

ArrayList<Thing> myThings = new ArrayList<Thing>();
kSession.setGlobal("myThings", myThings);

В ваших файлах DRL должно быть хотя бы одно совпадение:

global ArrayList<Thing> myThings;

В противном случае вы получите:

java.lang.RuntimeException: Unexpected global [myThings]
at org.drools.core.impl.StatefulKnowledgeSessionImpl.setGlobal(StatefulKnowledgeSessionImpl.java:1200)
at com.sample.ThingTest.test(ThingTest.java:37)
person Jeff Taylor    schedule 09.08.2020