Почему я всегда получал неожиданную глобальную ошибку от слюней? - PullRequest
0 голосов
/ 17 января 2019

Когда я запускаю правила, я получаю странную ошибку.
Сведения об ошибке

java.lang.RuntimeException: Unexpected global [validateResult]
    at org.drools.core.impl.StatefulKnowledgeSessionImpl.setGlobal(StatefulKnowledgeSessionImpl.java:1209)
    at com.hikedu.backend.service.impl.signupproject.SignUpProjectServiceImpl.validate(SignUpProjectServiceImpl.java:190)
    at com.hikedu.backend.service.impl.signupproject.SignUpProjectServiceImpl.validate(SignUpProjectServiceImpl.java:204)
    at com.hikedu.backend.service.impl.signupproject.SignUpProjectServiceImpl.signUp(SignUpProjectServiceImpl.java:102)
    at com.hikedu.backend.controller.ProjectApplicationRecordController.signUp(ProjectApplicationRecordController.java:94)
    at com.hikedu.backend.controller.ProjectApplicationRecordController$$FastClassBySpringCGLIB$$dc339407.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)

Вот мой код для запуска правил

    KieSession session = sessionBuilder.build(theDsl);
    ProjectVersion latestVersion = projectVersionService.getLatestVersionIfNotExistsThenThrowException(projectId);
    User user = userService.getUserIfNotExistsThenThrowException(userId);
    ApplicationInfo info = getTheInsertObj(userId, projectId);
    ProjectSignUpValidateResultDTO resultDTO = new ProjectSignUpValidateResultDTO();
    resultDTO.setPass(true);
    session.setGlobal("validateResult", resultDTO);
    session.insert(latestVersion);
    session.insert(info);
    session.insert(user);
    session.fireAllRules(1);
    session.dispose();

    return resultDTO;

Я много искал об этой ошибке. Все ответы говорят об одном и том же: файл dsl должен объявить глобальное, а объявленное имя и путь должны быть эквивалентны приведенному коду Но я снова и снова подтверждаю, что мой dsl и мой код там не нашли никаких ошибок.

Я пытался изменить глобальное имя на другое, но все равно получаю эту ошибку.

Так что, пожалуйста, помогите мне.

вот мой дсл

import com.hikedu.backend.model.User;
import com.hikedu.backend.model.ProjectVersion;
import java.util.Map;
import com.hikedu.backend.dto.signupproject.ApplicationInfo
import java.util.Date
import java.sql.Timestamp

global com.hikedu.backend.dto.project.ProjectSignUpValidateResultDTO validateResult

rule "department not match"
no-loop
when
    $p : ProjectVersion()
    $u : User($p.applicationRequirements.departmentId not contains departmentOfJoined.id)
then
    validateResult.setPass(false);
    validateResult.setTheReasonOfUnPass("some reason");
end

И я сделал отладку, чтобы проверить глобальные переменные сессии. Вот результат отладки enter image description here

Используемая мной версия drools enter image description here

Вот метод KieSessionBuilder.build

@Override
    public KieSession build(String dsl) {
        if (dsl == null) {
            throw new RuntimeException("Dsl cannot be null");
        }
        KieHelper helper = new KieHelper();
        helper.setClassLoader(getClass().getClassLoader());
        helper.addContent(dsl, ResourceType.DSL);
        KieBase base = helper.build();
        return base.newKieSession();
    }

Спасибо вам всем. Мой английский не очень хорошо, пожалуйста, прости меня.

Ответы [ 3 ]

0 голосов
/ 18 января 2019

Я самостоятельно исправил ошибку. Вот решение:

Изменить способ сборки дрл.

@Override
public KieSession build(String drl) {
    if (drl == null) {
        throw new RuntimeException("Drl cannot be null");
    }

    kieFileSystem.write("src/main/resources/" + drl.hashCode() + ".drl", kieServices.getResources().newReaderResource(new StringReader(drl)));
    KieBuilder builder = kieServices.newKieBuilder(kieFileSystem).buildAll();

    Results results = builder.getResults();
    if (results.hasMessages(Message.Level.ERROR)) {
        throw new IllegalStateException("##errors : " + results.getMessages());
    }

    KieContainer container = kieServices.newKieContainer(builder.getKieModule().getReleaseId());

    return container.newKieSession();
}

После того, как я изменил способ сборки, drl получил еще одну ошибку:

java.lang.RuntimeException: Illegal class for global. Expected [com.hikedu.backend.dto.project.ProjectSignUpValidateResultDTO], found [com.hikedu.backend.dto.project.ProjectSignUpValidateResultDTO].
    at org.drools.core.impl.StatefulKnowledgeSessionImpl.setGlobal(StatefulKnowledgeSessionImpl.java:1211)
    at com.hikedu.backend.service.impl.signupproject.SignUpProjectServiceImpl.validate(SignUpProjectServiceImpl.java:190)
    at com.hikedu.backend.service.impl.signupproject.SignUpProjectServiceImpl.validate(SignUpProjectServiceImpl.java:204)
    at com.hikedu.backend.service.impl.signupproject.SignUpProjectServiceImpl.signUp(SignUpProjectServiceImpl.java:102)
    at com.hikedu.backend.controller.ProjectApplicationRecordController.signUp(ProjectApplicationRecordController.java:94)
    at com.hikedu.backend.controller.ProjectApplicationRecordController$$FastClassBySpringCGLIB$$dc339407.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)

Я много искал об этой новой ошибке. И наконец получил решение. Эта ошибка, потому что я использую devtools в моем проекте. И devtools будет использовать сам загрузчик классов для загрузки всего класса. Но слюни загружают класс другим загрузчиком классов.

Вот отладочная информация:

Тип загружается слюнями. enter image description here

Значение загружается devtools enter image description here

Как это решить? Просто добавьте файл META-INF / spring-devtools.properties. Содержание

restart.include.drools=/drools-[\\s\\S]+\.jar
restart.include.kie=/kie-[\\s\\S]+\.jar

Это обеспечит загрузку drools и kie загрузчиком классов devtools. И тогда ошибка исправлена.

Вот документ

https://github.com/spring-projects/spring-boot/issues/3316

https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html

0 голосов
/ 24 апреля 2019

Опаздывает на вечеринку, но у меня была та же ошибка, но по другой причине. Я менял систему с использованием Drools 7.0.12 с сеанса без сохранения состояния на сеанс с сохранением состояния. Похоже, что в сеансе с состоянием Drools проверяет, что глобальный элемент определен хотя бы в одном файле .drl. Если в файле .drl отсутствует «глобальное» определение, возникает непредвиденная глобальная ошибка. В сеансе без сохранения состояния такая проверка не выполняется.

0 голосов
/ 17 января 2019

Это выглядит странно. Не могли бы вы добавить глобальный тип в качестве импорта, а затем использовать тип без полного имени? Я имею в виду это:

import com.hikedu.backend.dto.project.ProjectSignUpValidateResultDTO;

global ProjectSignUpValidateResultDTO validateResult
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...