能否在Quarkus中用TimeFold/OptaPlanner解决多类型规划问题?
解决Quarkus中TimeFold多@PlanningSolution类的构建错误
错误原因
Quarkus的TimeFold扩展默认会自动扫描并注册所有带有@PlanningSolution注解的类,但该机制仅支持单个规划解决方案类,当存在多个时就会触发构建错误。
解决方案
1. 禁用自动发现解决方案
在src/main/resources/application.properties中添加配置,关闭自动扫描:
quarkus.timefold.solver.auto-discover-solutions=false
2. 手动创建并注册多个SolverManager实例
创建CDI生产者类,为每个规划解决方案手动加载对应的Solver配置,并生成独立的SolverManager bean:
import ai.timefold.solver.core.api.solver.SolverManager; import ai.timefold.solver.core.config.solver.SolverConfig; import ai.timefold.solver.quarkus.runtime.TimefoldRecorder; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; @ApplicationScoped public class SolverManagerProducer { private final TimefoldRecorder timefoldRecorder; // 注入TimefoldRecorder以确保Quarkus扩展能正确处理Solver配置 public SolverManagerProducer(TimefoldRecorder timefoldRecorder) { this.timefoldRecorder = timefoldRecorder; } // 为Solution1Table生成SolverManager @Produces @ApplicationScoped public SolverManager<Solution1Table, Long> solution1SolverManager() { SolverConfig solverConfig = SolverConfig.createFromXmlResource("solution1SolverConfig.xml"); timefoldRecorder.registerSolverConfig(solverConfig); return SolverManager.create(solverConfig); } // 为Solution2Table生成SolverManager @Produces @ApplicationScoped public SolverManager<Solution2Table, Long> solution2SolverManager() { SolverConfig solverConfig = SolverConfig.createFromXmlResource("solution2SolverConfig.xml"); timefoldRecorder.registerSolverConfig(solverConfig); return SolverManager.create(solverConfig); } }
3. 在业务代码中注入使用
在需要求解的类中,分别注入对应的SolverManager实例进行使用:
import jakarta.inject.Inject; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; @Path("/solve") public class SolveResource { @Inject SolverManager<Solution1Table, Long> solution1SolverManager; @Inject SolverManager<Solution2Table, Long> solution2SolverManager; @POST @Path("/solution1") public String startSolution1Solve(Solution1Table problem) { Long problemId = 1L; solution1SolverManager.solve(problemId, problem, (id, solution) -> { // 处理Solution1的求解结果逻辑 }); return "Solution1求解任务已启动"; } @POST @Path("/solution2") public String startSolution2Solve(Solution2Table problem) { Long problemId = 2L; solution2SolverManager.solve(problemId, problem, (id, solution) -> { // 处理Solution2的求解结果逻辑 }); return "Solution2求解任务已启动"; } }
注意事项
- 确保每个
SolverConfig.createFromXmlResource()传入的XML文件名与src/main/resources下的配置文件完全匹配。 - 通过
TimefoldRecorder.registerSolverConfig()注册配置,能保证Quarkus的TimeFold扩展提供的监控、指标等功能正常工作。
内容的提问来源于stack exchange,提问作者Alexey
相关产品推荐
相关产品推荐

