I'm trying to run an OptaPlanner benchmark with the following configuration:
<?xml version="1.0" encoding="UTF-8"?>
<plannerBenchmark xmlns="https://www.optaplanner.org/xsd/benchmark" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.optaplanner.org/xsd/benchmark https://www.optaplanner.org/xsd/benchmark/benchmark.xsd">
<benchmarkDirectory>data/acme</benchmarkDirectory>
<inheritedSolverBenchmark>
<solver>
<solutionClass>org.acme.domain.Main</solutionClass>
<entityClass>org.acme.domain.Standstill</entityClass>
<entityClass>org.acme.domain.Visit</entityClass>
<scoreDirectorFactory>
<constraintProviderClass>org.acme.solver.MainConstraintProvider</constraintProviderClass>
<initializingScoreTrend>ONLY_DOWN</initializingScoreTrend>
</scoreDirectorFactory>
<termination>
<secondsSpentLimit>30</secondsSpentLimit>
</termination>
</solver>
<problemBenchmarks>
<solutionFileIOClass>org.acme.bootstrap.AcmeSolutionIO</solutionFileIOClass>
<inputSolutionFile>data/latest.xml</inputSolutionFile>
</problemBenchmarks>
</inheritedSolverBenchmark>
<solverBenchmark>
<solver>
<constructionHeuristic>
<constructionHeuristicType>FIRST_FIT</constructionHeuristicType>
</constructionHeuristic>
<localSearch>
<localSearchType>LATE_ACCEPTANCE</localSearchType>
</localSearch>
</solver>
</solverBenchmark>
</plannerBenchmark>
However, I get this error message:
Exception in thread "main" org.optaplanner.benchmark.api.PlannerBenchmarkException: Benchmarking failed: failureCount (1). The exception of the firstFailureSingleBenchmarkRunner (blankData_Config_0_0) is chained.
at org.optaplanner.benchmark.impl.DefaultPlannerBenchmark.benchmarkingEnded(DefaultPlannerBenchmark.java:326)
at org.optaplanner.benchmark.impl.DefaultPlannerBenchmark.benchmark(DefaultPlannerBenchmark.java:100)
at org.optaplanner.benchmark.impl.DefaultPlannerBenchmark.benchmarkAndShowReportInBrowser(DefaultPlannerBenchmark.java:424)
at org.acme.bootstrap.BenchmarkApp.main(BenchmarkApp.kt:29)
Caused by: java.lang.IllegalStateException: The class (class java.lang.Long) should have a no-arg constructor to create a planning clone.
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner.lambda$retrieveCachedConstructor$0(FieldAccessingSolutionCloner.java:90)
at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
at org.optaplanner.core.impl.domain.common.ConcurrentMemoization.computeIfAbsent(ConcurrentMemoization.java:44)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner.retrieveCachedConstructor(FieldAccessingSolutionCloner.java:85)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner$FieldAccessingSolutionClonerRun.constructClone(FieldAccessingSolutionCloner.java:158)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner$FieldAccessingSolutionClonerRun.clone(FieldAccessingSolutionCloner.java:150)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner$FieldAccessingSolutionClonerRun.process(FieldAccessingSolutionCloner.java:207)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner$FieldAccessingSolutionClonerRun.processQueue(FieldAccessingSolutionCloner.java:194)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner$FieldAccessingSolutionClonerRun.cloneSolution(FieldAccessingSolutionCloner.java:136)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner.cloneSolution(FieldAccessingSolutionCloner.java:73)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.cloneSolution(AbstractScoreDirector.java:257)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.cloneWorkingSolution(AbstractScoreDirector.java:250)
at org.optaplanner.core.impl.solver.recaller.BestSolutionRecaller.updateBestSolutionAndFire(BestSolutionRecaller.java:129)
at org.optaplanner.core.impl.constructionheuristic.DefaultConstructionHeuristicPhase.phaseEnded(DefaultConstructionHeuristicPhase.java:146)
at org.optaplanner.core.impl.constructionheuristic.DefaultConstructionHeuristicPhase.solve(DefaultConstructionHeuristicPhase.java:98)
at org.optaplanner.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:99)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:192)
at org.optaplanner.benchmark.impl.SubSingleBenchmarkRunner.call(SubSingleBenchmarkRunner.java:122)
at org.optaplanner.benchmark.impl.SubSingleBenchmarkRunner.call(SubSingleBenchmarkRunner.java:42)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NoSuchMethodException: java.lang.Long.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3585)
at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2754)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner.lambda$retrieveCachedConstructor$0(FieldAccessingSolutionCloner.java:88)
... 22 more
I've tried many other benchmark configs including with <solverBenchmarkBluePrintType>CONSTRUCTION_HEURISTIC_WITH_AND_WITHOUT_LOCAL_SEARCH</solverBenchmarkBluePrintType>
but none of them work either.
I had it working previously, but I went back to it after a number of changes and it no longer works.
I'm using a SimpleLongScore
now instead of a SimpleScore
and I'm wondering if that has anything to do with the error since before it wasn't throwing this exception.
Any ideas?
Edit #1:
I wish I could provide more code, but I really don't know what code to include.
The bizarre thing is that OptaPlanner runs just fine through mvn compile quarkus:dev
, but when I run my benchmark app, from the main entry, it gives the errors as mentioned before, java.lang.IllegalStateException: The class (class java.lang.Long) should have a no-arg constructor to create a planning clone.
Here's my main:
fun main(args: Array<String>) {
val plannerBenchmarkFactory:PlannerBenchmarkFactory = PlannerBenchmarkFactory.createFromXmlResource("benchmarkBluePrintConfig.xml")
val plannerBenchmark: PlannerBenchmark = plannerBenchmarkFactory.buildPlannerBenchmark()
plannerBenchmark.benchmarkAndShowReportInBrowser()
}
The solverConfig.xml
can also be the same for both, but only the benchmark app throws the error. It's pretty odd to me.
I figured it out.
In my Visit
class I was using a @CustomShadowVariable
:
@DeepPlanningClone
@CustomShadowVariable(
variableListenerClass = ArrivalTimeUpdatingVariableListener::class,
sources = [PlanningVariableReference(variableName = "previousStandstill")]
)
var arrivalTime: Long? = null
Removing @DeepPlanningClone
solved the problem.
I have no idea why it runs fine when the SolverManager
is @Inject
'd as opposed to throwing the error when SolverConfig
/SolverManager
is created through the API (as it is in my Benchmark App).