Java Optaplanner项目的非法参数异常,解算器配置在类加载器中不作为类路径资源存在
在解算器类中运行SpringBoot应用程序时出错。我试图从resources文件夹中包含的xml资源创建解算器工厂,就像OptaPlanner的员工排班示例一样,但是我遇到了一个非法的参数异常,我不知道为什么。我尝试将xml文件移动到与解算器类相同的文件夹中,但出现了相同的错误。我不知道为什么在遵循OptaPlanner为员工排班提供的示例代码时抛出异常 下面是我的解算器类的代码:Java Optaplanner项目的非法参数异常,解算器配置在类加载器中不作为类路径资源存在,java,spring-boot,optaplanner,Java,Spring Boot,Optaplanner,在解算器类中运行SpringBoot应用程序时出错。我试图从resources文件夹中包含的xml资源创建解算器工厂,就像OptaPlanner的员工排班示例一样,但是我遇到了一个非法的参数异常,我不知道为什么。我尝试将xml文件移动到与解算器类相同的文件夹中,但出现了相同的错误。我不知道为什么在遵循OptaPlanner为员工排班提供的示例代码时抛出异常 下面是我的解算器类的代码: package com.schedule.demo.solver; import com.schedule.d
package com.schedule.demo.solver;
import com.schedule.demo.domain.Roster;
import com.schedule.demo.service.RosterService;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import org.optaplanner.core.api.solver.Solver;
import org.optaplanner.core.api.solver.SolverFactory;
import org.optaplanner.core.impl.score.director.ScoreDirector;
import org.optaplanner.core.impl.score.director.ScoreDirectorFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.ApplicationScope;
@ApplicationScope
@Component
public class ScheduleSolverManager implements ApplicationRunner {
public static final String SOLVER_CONFIG = "com/schedule/demo/service/solver/scheduleSolverConfig.xml";
protected final transient Logger logger = LoggerFactory.getLogger(getClass());
private SolverFactory<Roster> rosterSolverFactory;
private ScoreDirectorFactory<Roster> rosterScoreDirectorFactory;
private ThreadPoolTaskExecutor taskExecutor;
private ConcurrentMap<Integer, Solver<Roster>> deptIdToSolverMap = new ConcurrentHashMap<>();
private RosterService rosterService;
public ScheduleSolverManager(ThreadPoolTaskExecutor taskExecutor, RosterService rosterService){
this.taskExecutor = taskExecutor;
this.rosterService = rosterService;
}
@Override
public void run(ApplicationArguments args) throws Exception {
setupRosterSolverFactory();
}
private void setupRosterSolverFactory() {
rosterSolverFactory = SolverFactory.createFromXmlResource("com/schedule/demo/service/solver/scheduleSolverConfig.xml", ScheduleSolverManager.class.getClassLoader());
rosterScoreDirectorFactory = rosterSolverFactory.buildSolver().getScoreDirectorFactory();
}
public CountDownLatch solve(Integer deptID){
final CountDownLatch solvingEndedLatch = new CountDownLatch(1);
try{
taskExecutor.execute(()->{
Solver<Roster> rosterSolver = rosterSolverFactory.buildSolver();
deptIdToSolverMap.put(deptID, rosterSolver);
rosterSolver.addEventListener(event -> {
if(event.isEveryProblemFactChangeProcessed()){
logger.info("New best solution found for deptId ({}).", deptID);
Roster newRoster = event.getNewBestSolution();
rosterService.updateShiftsOfRoster(newRoster);
}
});
Roster roster = rosterService.buildRoster(deptID);
try {
rosterSolver.solve(roster);
solvingEndedLatch.countDown();
} finally {
deptIdToSolverMap.remove(deptID);
}
});
} catch (Throwable e) {
logger.error("Error solving for deptId (" + deptID + ").", e);
}
return solvingEndedLatch;
}
public Roster getRoster(final Integer deptId){
Solver<Roster> rosterSolver = deptIdToSolverMap.get(deptId);
return rosterSolver == null ? null : rosterSolver.getBestSolution();
}
public ScoreDirector<Roster> getScoreDirector() {
return rosterScoreDirectorFactory.buildScoreDirector();
}
}
package com.schedule.demo.solver;
导入com.schedule.demo.domain.花名册;
导入com.schedule.demo.service.RosterService;
导入java.util.concurrent.ConcurrentHashMap;
导入java.util.concurrent.ConcurrentMap;
导入java.util.concurrent.CountDownLatch;
导入org.optaplanner.core.api.solver.solver;
导入org.optaplanner.core.api.solver.SolverFactory;
导入org.optaplanner.core.impl.score.director.ScoreDirector;
导入org.optaplanner.core.impl.score.director.ScoreDirectorFactory;
导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
导入org.springframework.boot.ApplicationArguments;
导入org.springframework.boot.ApplicationRunner;
导入org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
导入org.springframework.stereotype.Component;
导入org.springframework.web.context.annotation.ApplicationScope;
@应用范围
@组成部分
公共类ScheduleSolverManager实现ApplicationRunner{
public static final String SOLVER_CONFIG=“com/schedule/demo/service/SOLVER/scheduleSolverConfig.xml”;
受保护的最终瞬态记录器Logger=LoggerFactory.getLogger(getClass());
私人溶剂厂罗斯特溶剂厂;
私人ScoreDirectorFactory名册CoreDirectorFactory;
私有线程池taskExecutor taskExecutor;
私有ConcurrentMap deptIdToSolverMap=新ConcurrentHashMap();
私人名册服务;
公共ScheduleSolverManager(ThreadPoolTaskExecutor taskExecutor,RosterService RosterService){
this.taskExecutor=taskExecutor;
this.rosterService=rosterService;
}
@凌驾
公共void运行(ApplicationArguments参数)引发异常{
setupRosterSolverFactory();
}
私有void setupRosterSolverFactory(){
rosterSolverFactory=SolverFactory.createFromXmlResource(“com/schedule/demo/service/solver/scheduleSolverConfig.xml”,ScheduleSolverManager.class.getClassLoader());
rosterScoreDirectorFactory=rosterSolverFactory.buildSolver().getScoreDirectorFactory();
}
公共倒计时锁存器解算(整数deptID){
最终倒计时闩锁SolvingEndLatch=新倒计时闩锁(1);
试一试{
taskExecutor.execute(()->{
解算器rosterSolver=rosterSolverFactory.buildSolver();
deptIdToSolverMap.put(deptID,rosterSolver);
rosterSolver.addEventListener(事件->{
if(event.isEveryProblemFactChangeProcessed()){
info(“为deptId({})找到了新的最佳解决方案”。”,deptId);
花名册newfloster=event.getNewTestSolution();
rosterService.UpdateShiftsOfloster(新花名册);
}
});
花名册=花名册服务.构建花名册(deptID);
试一试{
求解(花名册);
solvingEndedLatch.countDown();
}最后{
deptIdToSolverMap.remove(deptID);
}
});
}捕获(可丢弃的e){
logger.error(“deptId的错误解决(“+deptId+”),e);
}
返回SolvingEndelatch;
}
公共花名册获取花名册(最终整数deptId){
解算器rosterSolver=deptIdToSolverMap.get(deptId);
返回rosterSolver==null?null:rosterSolver.getBestSolution();
}
公共ScoreDirector getScoreDirector(){
返回rosterScoreDirectorFactory.buildScoreDirector();
}
}
运行时的错误如下所示:
Caused by: java.lang.IllegalArgumentException: The solverConfigResource (com/schedule/demo/service/solver/scheduleSolverConfig.xml) does not exist as a classpath resource in the classLoader (org.springframework.boot.devtools.restart.classloader.RestartClassLoader@2302b8ed).
原因:java.lang.IllegalArgumentException:solverConfigResource(com/schedule/demo/service/solver/scheduleSolverConfig.xml)在类加载器(org.springframework.boot.devtools.restart.classLoader)中不作为类路径资源存在。RestartClassLoader@2302b8ed).
使用
optaplanner spring boot starter
它大大简化了spring集成
指南:
视频:
如果您不想使用初学者,此代码可能会修复它:
SolverFactory.createFromXmlResource(“com/schedule/demo/service/solver/scheduleSolverConfig.xml”,花名册.class.getClassLoader())
(使用花名册的类加载器)。使用optaplanner spring boot starter
它大大简化了spring集成
指南:
视频:
如果您不想使用初学者,此代码可能会修复它:SolverFactory.createFromXmlResource(“com/schedule/demo/service/solver/scheduleSolverConfig.xml”,花名册.class.getClassLoader())
(使用花名册的类加载器。您必须将解算器配置XML放置在src/main/resources
下,才能将其作为类路径资源加载
因此,如果使用资源名com/schedule/demo/service/solver/scheduleSolverConfig.xml
加载它,那么文件必须位于
src/main/resources/com/schedule/demo/service/solver/scheduleSolverConfig.xml
必须将解算器配置XML放在src/main/resources
下,才能将其作为类路径资源加载
因此,如果使用资源名com/schedule/demo/service/solver/scheduleSolverConfig.xml
加载它,那么文件必须位于
src/main/resources/com/schedule/demo/service/solver/scheduleSolverConfig.xml
您的“解决方案”包