简体   繁体   English

版本升级后异常

[英]Exception after version upgrade

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 :在使用 Optaplanner v7.11.0.Final 的项目上出现 Score 持久性问题,我升级到最新版本 (v7.25.0.Final) 但出现以下异常:

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.终于发现升级到v7.17.0.Final时没有出现异常。

What have been done in since v7.18.0.Final that makes the code failing ?自 v7.18.0.Final 以来做了什么导致代码失败?

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)

My theory:我的理论:

Your code already had a bug, but in 7.11, OptaPlanner didn't detect it and didn't fail-fast.您的代码已经有一个错误,但在 7.11 中,OptaPlanner 没有检测到它,也没有快速失败。 Starting from 7.18, it does detect and fail-fast, to help you ...从 7.18 开始,它会检测和快速失败,以帮助您...

As far as I can tell without the stacktrace, a method like ScoreDirector.lookUpWorkingObject() fails fast, probably in a callback given to addProblemFactChange() or in multithreaded solving.据我所知,没有ScoreDirector.lookUpWorkingObject() ,像ScoreDirector.lookUpWorkingObject()这样的方法失败很快,可能是在给addProblemFactChange()的回调中或在多线程解决中。 In any case, it can't find the working entity based upon the planningId of that entity.在任何情况下,它都无法根据该实体的 PlanningId 找到工作实体。

Notice how error message says the planningId (usually a Long , String , UUID ) is an instance of class plr.domain.Etat$HibernateProxy$EZnO4cSz .请注意错误消息如何说明 PlanningId (通常是LongStringUUID )是plr.domain.Etat$HibernateProxy$EZnO4cSz类的一个实例。 That countradicts your domain model in your question, which says it's an Integer.这会影响您在问题中的域模型,它说它是一个整数。 Put a breakpoint where the message is thrown and validate this please.在抛出消息的地方放置一个断点并验证这一点。

Potential causes: - mixing in attached JPA objects in general - which I would doubt - mixing in attached JPA objects and using OptaPlanner's @PlanningId annotation on a method that doesn't have the JPA @Id annotation, causing JPA to proxy that method.潜在原因: - 一般混入附加的 JPA 对象 - 我会怀疑 - 混入附加的 JPA 对象并在没有 JPA @Id 注释的方法上使用 OptaPlanner 的 @PlanningId 注释,导致 JPA 代理该方法。

Either way, detaching the JPA objects before working with them in OptaPlanner will fix it.无论哪种方式,在 OptaPlanner 中使用 JPA 对象之前分离它们都会修复它。 Please confirm if that fixes it, so I can add a "Maybe detach your JPA objects" in the error message.请确认是否修复了它,以便我可以在错误消息中添加“也许分离您的 JPA 对象”。

Thanks to Geoffrey answer and yurloc comments, I finally found what was the problem.感谢Geoffrey 的回答yurloc 的评论,我终于找到了问题所在。

First, Etat objects were coming through a join with another object.首先, Etat对象是通过与另一个对象连接而来的。 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.ManyToOne fetch 类型更改为Eager而不是Lazy表明我得到了相同的异常,但使用Etat对象而不是它们的 Hibernate 代理。

So it means that these objects were not know by Optaplanner.所以这意味着 Optaplanner 不知道这些对象。 Indeed, I was using a specific range per planning variable for Etat but never load all these ones in the problem facts.事实上,我为Etat使用了每个计划变量的特定范围,但从未在问题事实中加载所有这些。

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.最后,它与分离对象和附加对象无关,连接获取类型可以放回Lazy值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM