Spring boot OptaPlanner在Spring引导中出现java反射错误
我刚刚尝试在Spring Boot中运行OptaPlanner项目,但在OptaPlanner Spring用户指南中只有非常简单的文本 实际上,我认为将所有域对象、配置文件和drools文件从OptaPlanner项目复制到Spring Boot项目是非常容易的,而不做任何更改,但唯一的问题是如何调用Spring boot OptaPlanner在Spring引导中出现java反射错误,spring-boot,reflection,optaplanner,Spring Boot,Reflection,Optaplanner,我刚刚尝试在Spring Boot中运行OptaPlanner项目,但在OptaPlanner Spring用户指南中只有非常简单的文本 实际上,我认为将所有域对象、配置文件和drools文件从OptaPlanner项目复制到Spring Boot项目是非常容易的,而不做任何更改,但唯一的问题是如何调用Solver的solve方法 我让它在Spring启动后运行,并使用一个类(名为CommandLineAppStartupRunner)实现了CommandLineRunner接口,我在它的run
Solver
的solve
方法
我让它在Spring启动后运行,并使用一个类(名为CommandLineAppStartupRunner
)实现了CommandLineRunner
接口,我在它的run
方法中调用了solve
方法。最后,我得到一个例外,如下所示:
Caused by: java.lang.IllegalArgumentException: Can not set org.optaplanner.core.api.score.buildin.hardmediumsoft.HardMediumSoftScore field springbootcloudbalance.domain.CloudBalance.score to springbootcloudbalance.domain.CloudBalance
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)
at java.lang.reflect.Field.get(Field.java:393)
at org.optaplanner.core.impl.domain.common.accessor.ReflectionFieldMemberAccessor.executeGetter(ReflectionFieldMemberAccessor.java:54)
at org.optaplanner.core.impl.domain.solution.descriptor.SolutionDescriptor.getScore(SolutionDescriptor.java:1071)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.cloneSolution(AbstractScoreDirector.java:212)
at org.optaplanner.core.impl.solver.scope.DefaultSolverScope.setWorkingSolutionFromBestSolution(DefaultSolverScope.java:230)
at org.optaplanner.core.impl.solver.AbstractSolver.solvingStarted(AbstractSolver.java:75)
at org.optaplanner.core.impl.solver.DefaultSolver.solvingStarted(DefaultSolver.java:210)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:190)
at springbootcloudbalance.CommandLineAppStartupRunner.run(CommandLineAppStartupRunner.java:55)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:818)
... 10 common frames omitted
我检查了代码,发现异常抛出,因为field.getDeclaringClass()
中的对象与var1.getClass()
中的对象是不同的实例。恐怕这是由于OptaPlanner和Spring Boot之间的java反射实现冲突造成的
我使用的版本如下:
- OptaPlanner 7.11.0.1决赛
- 弹簧防尘套2.0.5.1版本
- JVM 1.8.0_181
尼克的回答是正确的。这只是为了弄清楚发生了什么 此行表示optaplanner正在提取
CloudBalance.getScore()
:
这一行意味着它使用了一个ReflectionFieldMemberAccessor
,这是通过反射读取字段(包括私有字段)的方法:
现在,错误消息是它变得有趣的地方:
Can not set ...HardMediumSoftScore field ...CloudBalance.score to ...CloudBalance
看起来基本上是这样:
CloudBalance cloudBalance2 = cloudBalance.getScore();
嗯?穆萨提供了这个答案,但有人删除了它,尽管JIRA链接非常相关,因为它指出了哪个版本的OptaPlanner可以更好地处理这个问题:
“向OptaPlanner提交了一个问题,以便为此类情况提供更好的错误消息:。请随意添加任何评论或建议。”Spring Boot和OptaPlanner完全能够协同工作,因此我猜这一定是您的代码中的某些内容。这将有助于查看更多的runner类和解决方案类。您好,您可以从中查看代码。此外,如果将OptaPlanner相关代码从
CommandLineAppStartupRunner
移动到main
函数,这意味着它不是springboot应用程序,而是普通java应用程序,那么它工作正常。删除spring boot devtools依赖项为我修复了它,因此显然该依赖项确实会以某种方式干扰反射。我以前在自己的项目中看到过这一点。解释可能与此问题的公认答案相同:。另外,在使用dev-tools依赖项时,在XML配置中使用scannectedclass也可以使其工作(而不是手动定义解决方案和实体类)。我建议禁用它,因为问题已提交给OptaPlanner,以便为此类情况提供更好的错误消息:。请随意添加任何评论或建议。boot devtools的作用是什么?OptaPlanner和它真的应该是兼容的。我们很有兴趣知道如何允许这一点。我恐怕有一件事无法解释为什么ScanAnnotatedClass
与spring boot devtools
一起工作,但是solutionClass
和entityClass
不使用spring boot devtools
使项目资源和库由分离类装入器。可能还有其他原因。。。
Can not set ...HardMediumSoftScore field ...CloudBalance.score to ...CloudBalance
CloudBalance cloudBalance2 = cloudBalance.getScore();