【问题标题】:OptaPlanner SolverManager Bean not being found in Spring application在 Spring 应用程序中找不到 OptaPlanner SolverManager Bean
【发布时间】:2020-04-22 17:28:11
【问题描述】:

我对使用 Spring 还很陌生,但遇到了一个似乎无法解决的问题。我正在尝试使用一个名为Optaplanner 的包。在这种情况下,我或多或少会跟随一个简单的课程安排程序,视频是here,我正在处理的部分发生在 51:00。

我的问题是,该过程的一个步骤需要依赖注入,当我构建/运行 Spring 应用程序时,我收到以下错误:

Description:

Field solverManager in com.java.optaplex.resource.MainResource required a bean of type 'org.optaplanner.core.api.solver.SolverManager' that could not be found.

The injection point has the following annotations:
    - @javax.inject.Inject()

Action:

Consider defining a bean of type 'org.optaplanner.core.api.solver.SolverManager' in your configuration.

Process finished with exit code 1

我使用 Gradle 来管理我的 optaplanner 包,我可以看到存在依赖项(它是一个名为 SolverManager 的接口)。但是,我无法弄清楚为什么它无法找到/生成 bean。我假设 Spring 会动态生成 bean,就像使用 @Autowired 装饰器时创建 JPA 存储库的 bean 一样。我尝试将 SolverManager 代码复制并粘贴到我的项目根目录下的自己的文件中,并在其上尝试了一些装饰器(例如@Component),希望 Spring 能够检测到它,但它仍然抛出相同的错误,我不确定是什么去做。

我在 GitHub here 上创建了一个非常简单的演示应用程序,但出现错误。错误在文件 src/main/java/com/java/optaplex/resource/MainResource.java

此外,在 IntelliJ 中,SolverManager 实例 solverManager(参见下面的代码)被突出显示并显示:

Could not autowire. No beans of 'SolverManager<Test, Long>' type found.

MainResource.java:

package com.java.optaplex.resource;

import com.java.optaplex.pojo.Test;
import org.optaplanner.core.api.solver.SolverManager;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.inject.Inject;

@RestController
@RequestMapping("/api")
public class MainResource {

    // THE OFFENDING LINE IS HERE
    @Inject
    SolverManager<Test, Long> solverManager;

    @GetMapping("/test")
    public Test test () {
        return new Test("Result message here");
    }

}

为了清楚起见,我在 Solver 管理器声明中的测试类是:

Test.java

package com.java.optaplex.pojo;

public class Test {

    private String message;

    public Test(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

我意识到我的示例代码实际上并没有使用 SolverManager,我只是希望构建时的错误停止,以便我可以继续开发它。我只是想提供一个导致错误的非常简单的案例。

最后,我的 Gradle 依赖项如下所示:

build.gradle:

plugins {
    id 'org.springframework.boot' version '2.2.6.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
    id 'java'
    id 'war'
}

group = 'com.java'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }

    // https://mvnrepository.com/artifact/org.optaplanner/optaplanner-core
    compile group: 'org.optaplanner', name: 'optaplanner-core', version: '7.36.1.Final'
    compile group: 'javax.inject', name: 'javax.inject', version: '1'
}

test {
    useJUnitPlatform()
}

【问题讨论】:

标签: java spring spring-boot dependency-injection optaplanner


【解决方案1】:

要使其正常工作,您只需将 @Inject 注释替换为 @Autowire

从 Spring 的最新版本开始,最佳实践是使用构造函数依赖注入而不是 @Autowire(不再需要注解,因为 Spring 会自动自动装配 bean。

试试这个:

@RestController
@RequestMapping("/api")
public class MainResource {

    // Just the definition here
    private SolverManager<Test, Long> solverManager;

    pubilc MainResource(SolverManager<Test, Long> solverManager) {

     // When Spring will start, the bean will be injected here and become 
     // available in this class
     this.solverManager = solverManager;

    }

    @GetMapping("/test")
    public Test test () {
         // .....
    }

    // Other controller methods .... 

}

我正在使用 IntelliJ,它也会向我报告错误。但是我使用的是我在这个答案中发布的相同代码并且它有效。

正如您所说,SolverManager bean 是在 optaplanner 工件内部配置的,我怀疑这里的问题只是使用了错误的注释。

IDE 错误也困扰着我!但目前它有效,我会这样离开它。如果我能找到解决方案,我会在此处添加。

【讨论】:

  • 我在 Intellij 中遇到了同样的问题。我无法启动应用程序。问题解决了吗?也许与 optaplanner-spring-boot-starter, optaplanner-spring-boot-autoconfigure ?
  • @slim 如果是 intellij 给你错误,也许你可以尝试用 maven/gradle 编译,看看是否可以正常工作。如果是,则意味着 Intellij 无法识别要使用的实现,因此为避免该问题进入Settings &gt; Build, Execution, Deployment &gt; Compiler &gt; Validation,然后暂时禁用Spring model,最后再次构建。如果一切正常你可以保留这个配置,这只是一个IDE问题,不会影响编译输出!
【解决方案2】:

我正在使用 OptaPlanner 使用 Spring Boot 开发路由优化的 API REST。我刚刚开始与 OptaPlanner 合作,有一次我遇到了同样的问题。我有'optaplanner-spring-boot-starter'并添加了spring-boot-configuration-processor',其想法是让bean创建配置允许在我的类中注入SolverManager,但没有成功。我还尝试更改为其他版本的 OptaPlanner,但没有成功。最后,我解决了添加 OptaPlanner 包含在其代码中的配置以及类“RouteOptimizerConfig”的问题。这个类创建了求解器的bean,这样我以后就可以注入它了。这个问题似乎与 OptaPlanner SolverManager 在某一时刻被覆盖有关。

试试这个并将这个类添加到你的项目中:

@Configuration
class SolverConfig {

    private final SolverFactory<VehicleRoutingSolution> solverFactory;

    SolverConfig (SolverFactory<VehicleRoutingSolution> solverFactory) {
        this.solverFactory = solverFactory;
    }

    @Bean
    Solver<VehicleRoutingSolution> solver() {
        return solverFactory.buildSolver();
    }
}

【讨论】:

  • 不要这样做,那是不必要的,而且很脆弱。相反,在您的build.gradle 文件中,添加对optaplanner-spring-boot-starter 的依赖项,就像在the sources 中一样。然后你会看到它抱怨,因为Test 没有@PlanningSolution 注释。
【解决方案3】:

事实证明,经过大量在线搜索和挖掘 Optaplanner Spring Boot 包后,SolverManager bean 并未提供给 Spring。看来开发的重点是 Quarkus 框架。

我认为这是一个试用 Quarkus 的好机会,一旦我进行了更改,我的代码就可以工作了。 Youtube 上有一些由首席开发人员 Geoffrey De Smet 制作的关于通过 Quarkus 设置 Optaplanner 的精彩视频。

【讨论】:

  • 嗨,你确定吗?实际上我已经将optaplanner-spring-boot-starter 工件添加到我的spring boot 项目中,即使我的IDE 报告SolverManager 类未找到自动装配,在快速搜索后我发现启动工件取决于@ 987654325@。如果你看里面有一个OptaPlannerAutoConfiguration 类,你会在那里找到SolverManager Spring Bean。事实上,我正在使用求解器管理器,除了 ide 错误,它可以工作!
  • 我忘了...你可以在这个页面上找到一个很好的介绍视频:optaplanner.org/compatibility/springBoot.html。顺便说一句,Spring 集成宣传得不是很好,主页上只有一个小链接:/ 找到它一定很幸运!
  • 我们将 optaplanner 7.38 的 spring boot 指南和 spring boot 示例带回家 - 从 7.38 开始,两者都将在文档和 zip 下载按钮中提供。
  • 好点,我在这里创建了一个jira:issues.redhat.com/browse/PLANNER-2006
  • 是的。但是如果你也使用 spring boot,你只能自动注入 SolverManager 等。如果你不使用spring boot,那么你必须自己调用SolverManager.create()。
猜你喜欢
  • 2019-07-02
  • 1970-01-01
  • 2014-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多