spring-boot - OptaPlanner 的 Drools 规则不会在类路径上使用 Spring Boot 的 devtools 触发,因此分数为零

标签 spring-boot drools optaplanner

我让 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/

相关文章:

java - Drools 适用于我的场景吗?如果不是还有什么?

java - Drools 从 session 中获取相同类型的对象

java - Branch And Bound 在 OptaPlanner 中不起作用

java - OptaPlanner 计划实体,即使没有可用的移动

java - Spring boot with testcontainers - 如何防止上下文重新加载时数据库初始化

java - Intellij 运行相同的 Spring Boot 项目,社区版本运行良好,但终极版本抛出错误

maven - 如何使用 Jenkins 部署 Spring Boot Maven 应用程序?

java - Spring boot Controller 无法找到 bean 类

drools - 如何实现规则 如果我只想执行一条规则而不是执行 Drools 规则引擎中的所有规则?

OptaPlanner - 实体从未添加到此 ScoreDirector 错误