我让 optaplanner 使用 drools 规则正常工作。
“突然”,在我做了一些改变之后,Optaplanner 不再把我的事实放在流口水的 kSession 中。
我记录了一些日志,我看到 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)
最佳答案
我正在使用 spring 开发工具根据源文件中的更改自动重新加载我的 web 应用程序。<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
这是问题。为了执行热重载,项目的所有资源和类都由spring的RestartClassLoader
加载和监视。但是库(依赖项,例如 Drools 和 Optaplanner)由 Base ClassLoader 加载(实际上是 AppClassLoader
)。因此问题。
要修复它,请配置 spring 开发工具以在 RestartClassLoader 中加载 Drools 库以及项目的类:
using-boot-devtools-customizing-classload
所以我的问题不是很好命名。 Drools 工作内存不为空,但包含不为instanceof
的对象我的类,因为不在同一个类加载器中。
为了理解这一点,我使用了以下规则:
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,因为类不“相同”。
关于spring-boot - OptaPlanner 的 Drools 规则不会在类路径上使用 Spring Boot 的 devtools 触发,因此分数为零,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35746370/