2016-03-02 2 views
1

У меня есть optaplanner, который работает правильно с правилами слюни. «Внезапно», после некоторых изменений, которые я сделал, Optaplanner больше не помещает мои факты в слюнки kSession.Рабочая память Drools Optaplanner пуста

я ставлю некоторое протоколирование, и я вижу, что optaplanner называет getProblemFacts() метод на моем решении, и этот метод возвращает список с размером> 0.

Я написал правило DRL просто сосчитать факты и запишите эти подсчеты (это правило проверено на единицу и хорошо работает, когда я сам помещаю объекты в ksession). Я также убежден, что optaplanner не помещает факты в рабочую память.

Фаза ConstructionHeuristics прекращается хорошо (и делает это задание, так как мои PlaningVariables больше не нуль после этой фазы). Я получил свою проблему только при начале LocalSearch.

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

У меня есть совет: Я использую <scanAnnotatedClasses/> и у вас есть эта проблема. Если я ставлю два класса «вручную» с помощью <solutionClass/> и <entityClass/> тогда я получаю ошибку отражения:

Exception in thread "Solver" java.lang.IllegalArgumentException: object is not an instance of declaring class 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:483) 
    at org.optaplanner.core.impl.domain.common.accessor.BeanPropertyMemberAccessor.executeGetter(BeanPropertyMemberAccessor.java:67) 
    at org.optaplanner.core.impl.domain.solution.descriptor.SolutionDescriptor.extractEntityCollection(SolutionDescriptor.java:626) 
    at org.optaplanner.core.impl.domain.solution.descriptor.SolutionDescriptor.getEntityCount(SolutionDescriptor.java:489) 
    at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner$FieldAccessingSolutionClonerRun.cloneSolution(FieldAccessingSolutionCloner.java:200) 
    at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner.cloneSolution(FieldAccessingSolutionCloner.java:70) 
    at org.optaplanner.core.impl.score.director.AbstractScoreDirector.cloneSolution(AbstractScoreDirector.java:147) 
    at org.optaplanner.core.impl.solver.scope.DefaultSolverScope.setWorkingSolutionFromBestSolution(DefaultSolverScope.java:197) 
    at org.optaplanner.core.impl.solver.DefaultSolver.solvingStarted(DefaultSolver.java:195) 
    at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:175) 
    at ****.services.impl.SolverServiceImpl.lambda$0(SolverServiceImpl.java:169) 
+0

Это последнее исключение очень странно. Поместите контрольную точку в 'BeanPropertyMemberAccessor.executeGetter()' и распечатайте 'propertyType' и' bean.getClass() 'здесь, я хочу лучше понять эту неверную конфигурацию, чтобы optaplanner мог получить более приятное сообщение об ошибке. –

+0

Что касается вашей первоначальной проблемы, поставьте точку останова отладки в DroolsScoreDirector # resetKieSession и следуйте по пути getWorkingFacts (который является getProblemFacts() и объектами планирования). –

+0

Вы выполняете любую магию загрузки классов, такую ​​как OSGi? –

ответ

1

Я использую утилиты spring dev для автоматической перезагрузки изменений в webapp uppon в исходных файлах.

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>

Это вопрос. Для выполнения горячей перезагрузки все ресурсы и классы проекта загружаются и просматриваются весной RestartClassLoader, но librairies (зависимости, например, Drools & Optaplanner) загружаются базовым ClassLoader (фактически AppClassLoader). Поэтому проблемы.

Чтобы это исправить, настроить весной Dev инструменты для загрузки Drools librairies в RestartClassLoader, вместе с классами проекта: using-boot-devtools-customizing-classload

Так что мой вопрос был не очень хорошо назван. Рабочая память Drools не пуста, но содержит объекты, которые не являются instanceof моими классами, потому что не в том же ClassLoader.

Чтобы понять это, я использовал следующее правило:

rule "countProblemFacts" 
when 
    $nLectures : Long() from accumulate($lectures : Lecture(), count($lectures)) 
    $nCourses : Long() from accumulate($courses : Course(), count($courses)) 
    $nRooms : Long() from accumulate($rooms : Room(), count($rooms)) 
    $nPeriods : Long() from accumulate($periods : Period(), count($periods)) 
    $nObjects : Long() from accumulate($objects : Object(), count($objects)) 
then 
    DroolsUtil.log(drools, "Drools working memory");  
    DroolsUtil.log("Lectures:", $nLectures); 
    DroolsUtil.log("Courses:", $nCourses); 
    DroolsUtil.log("Rooms:", $nRooms); 
    DroolsUtil.log("Periods:", $nPeriods); 
    DroolsUtil.log("Objects:", $nObjects); 
    DroolsUtil.log(drools, "Total", ($nLectures + $nCourses + $nRooms + $nPeriods), "objects"); 
end 

$ nObjects рассчитывает до 12, все другие рассчитывают на 0, так как классы не «то же самое».

0

Проверьте getProblemFacts() метод. Использует ли он facts.add() вместо facts.addAll() при добавлении всех элементов коллекции к фактам проблемы?

+0

Я использую addAll. Я прочитал это время, и уже прочитал его в документах. :-) –

0

In my app I have everywhere an org.springframework.boot.devtools.restart.classloader.RestartClassLoader

Это не Загрузчик классов по умолчанию, так есть магия загрузки классов происходит. Согласно вашему комментарию, это не тот же загрузчик классов, который использовался для загрузки классов optaplanner. Таким образом, вы должны будете предоставить свой загрузчик классы:

Classloader classloader = TimeTable.class.getClassLoader(); 
... = SolverFactory.createFromXmlResource(".../solverConfig.xml", classloader); 

Это может быть необходимо обновить 6.4.0.Beta2, я в исправлен ряд передовых проблем загрузок классов в прошлом месяце.

+0

Я обновил до 6.4.0.Beta2 и использовал именно этот фрагмент кода. Но я все еще получаю Spring Classloader в 'BeanPropertyMemberAccessor' и' sun.misc.Launcher.AppClassLoader' для моего класса TimeTable. псих. В любом случае, я не думаю, что это проблема, потому что 'resetKieSession' получает правильную коллекцию« workFacts »со всеми фактами и строгальными объектами, и я вижу все необходимые вызовы на' kieSession.insert() '. Мое правило все равно ничего не получает. –

+0

Может быть, это правило - упростить его, поэтому невозможно сопоставить объект планирования. Если вы все равно получите его, добавьте его здесь, чтобы задать вопрос. –

+0

Но проблема с загрузкой классов меня больше интригует. Указание '' и '' должно всегда работать. На самом деле '' серьезно не рекомендуется в определенных средах (думаю, JDK 9 Jigsaw в настоящее время и т. Д.). Поэтому я хотел бы воспроизвести эту проблему - можно ли [отправить jira] (https://issues.jboss.org/projects/PLANNER) с помощью репродуктора? –

Смежные вопросы