Exception after version upgrade

Frédéric Praca :

Having problem with Score persistance on a project using Optaplanner v7.11.0.Final, I upgraded to the latest one (v7.25.0.Final) but got the following exception :

The externalObject (Etat(super=DbObject(id=11), libelle=RCD, ordre=60)) with planningId ((class plr.domain.Etat$HibernateProxy$EZnO4cSz,11)) has no known workingObject (null).
Maybe the workingObject was never added because the planning solution doesn't have a @ProblemFactCollectionProperty annotation on a member with instances of the externalObject's class (class plr.domain.Etat$HibernateProxy$EZnO4cSz).

I finally found that the exception does not appear when upgrading up to v7.17.0.Final.

What have been done in since v7.18.0.Final that makes the code failing ?

How to fix it ?

EDIT : For more information, here are the relative classes

package org.optaplanner.plr.domain;

import javax.persistence.Column;
import javax.persistence.Entity;

import org.optaplanner.core.api.domain.lookup.PlanningId;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Entity
public class Etat extends DbObject {

    @Column
    private String libelle;

    @Column
    private int ordre;

    @Override
    @PlanningId
    public Integer getId() {
        return super.getId();
    }
}

and its superclass

package org.optaplanner.plr.domain;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

import lombok.Data;
import lombok.EqualsAndHashCode;

@MappedSuperclass
@Data
@EqualsAndHashCode
public abstract class DbObject {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
}

and finally, the simplest config ever :)

<?xml version="1.0" encoding="UTF-8"?>
<solver>
    <!-- To solve faster by saturating multiple CPU cores -->
    <moveThreadCount>4</moveThreadCount>
    <solutionClass>org.optaplanner.plr.domain.PlannifSolution</solutionClass>
    <entityClass>org.optaplanner.plr.domain.Plannif</entityClass>
    <scoreDirectorFactory>
        <scoreDrl>org/optaplanner/plr/solver/score.drl</scoreDrl>
        <initializingScoreTrend>ONLY_DOWN</initializingScoreTrend>
    </scoreDirectorFactory>
    <termination>
        <secondsSpentLimit>1200</secondsSpentLimit>
        <unimprovedSecondsSpentLimit>300</unimprovedSecondsSpentLimit>
    </termination>
</solver>

The whole trace is

java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:782)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:763)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:318)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202)
    at org.optaplanner.plr.Application.main(Application.java:64)
Caused by: java.lang.IllegalStateException: The move thread with moveThreadIndex (2) has thrown an exception. Relayed here in the parent thread.
    at org.optaplanner.core.impl.heuristic.thread.OrderByMoveIndexBlockingQueue.take(OrderByMoveIndexBlockingQueue.java:142)
    at org.optaplanner.core.impl.localsearch.decider.MultiThreadedLocalSearchDecider.forageResult(MultiThreadedLocalSearchDecider.java:187)
    at org.optaplanner.core.impl.localsearch.decider.MultiThreadedLocalSearchDecider.decideNextStep(MultiThreadedLocalSearchDecider.java:157)
    at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.solve(DefaultLocalSearchPhase.java:70)
    at org.optaplanner.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:88)
    at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:191)
    at org.optaplanner.plr.Application$1.run(Application.java:222)
    at org.optaplanner.plr.Application$1$$FastClassBySpringCGLIB$$7557a0d1.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
    at org.optaplanner.plr.Application$1$$EnhancerBySpringCGLIB$$c098b4dc.run(<generated>)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:779)
    ... 5 common frames omitted
Caused by: java.lang.IllegalStateException: The externalObject (Etat(super=DbObject(id=11), libelle=RCD, ordre=60)) with planningId ((class org.optaplanner.plr.domain.Etat$HibernateProxy$YghGFDSA,11)) has no known workingObject (null).
Maybe the workingObject was never added because the planning solution doesn't have a @ProblemFactCollectionProperty annotation on a member with instances of the externalObject's class (class org.optaplanner.plr.domain.Etat$HibernateProxy$YghGFDSA).
    at org.optaplanner.core.impl.domain.lookup.PlanningIdLookUpStrategy.lookUpWorkingObject(PlanningIdLookUpStrategy.java:66)
    at org.optaplanner.core.impl.domain.lookup.LookUpManager.lookUpWorkingObject(LookUpManager.java:75)
    at org.optaplanner.core.impl.score.director.AbstractScoreDirector.lookUpWorkingObject(AbstractScoreDirector.java:509)
    at org.optaplanner.core.impl.heuristic.selector.move.generic.ChangeMove.rebase(ChangeMove.java:85)
    at org.optaplanner.core.impl.heuristic.selector.move.generic.ChangeMove.rebase(ChangeMove.java:33)
    at org.optaplanner.core.impl.heuristic.thread.MoveThreadRunner.run(MoveThreadRunner.java:139)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Frédéric Praca :

Thanks to Geoffrey answer and yurloc comments, I finally found what was the problem.

First, Etat objects were coming through a join with another object. Changing the ManyToOne fetch type to Eager instead of Lazy showed that I got the same exception but with Etat objects instead of their Hibernate proxies.

So it means that these objects were not know by Optaplanner. Indeed, I was using a specific range per planning variable for Etat but never load all these ones in the problem facts.

In the end, it has nothing to do with detached vs attached objects and the join fetch type can be put back to Lazy value.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=148325&siteId=1