Illegal argument exception for Optaplanner project, solver config does not exist as a classpath resource in the class loader

huangapple go评论81阅读模式
英文:

Illegal argument exception for Optaplanner project, solver config does not exist as a classpath resource in the class loader

问题

以下是您求翻译的代码部分:

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();
    }
}

请注意,上述内容是您提供的代码的翻译部分,如有任何疑问或需要进一步的帮助,请随时提问。

英文:

I am getting an error when running my SpringBoot application in my solver class. I am trying to create the solver factory from an xml resource contained in the resources folder exactly like the employee rostering example for OptaPlanner but I am getting an Illegal argument exception that I can't figure out why. I tried moving the xml file into the same folder as the solver class but the same error appears. I don't know why the exception is being thrown when I am following the example code that OptaPlanner has for employee rostering ?

Below is my code for my solver class:

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 = &quot;com/schedule/demo/service/solver/scheduleSolverConfig.xml&quot;;
protected final transient Logger logger = LoggerFactory.getLogger(getClass());
private SolverFactory&lt;Roster&gt; rosterSolverFactory;
private ScoreDirectorFactory&lt;Roster&gt; rosterScoreDirectorFactory;
private ThreadPoolTaskExecutor taskExecutor;
private ConcurrentMap&lt;Integer, Solver&lt;Roster&gt;&gt; deptIdToSolverMap = new ConcurrentHashMap&lt;&gt;();
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(&quot;com/schedule/demo/service/solver/scheduleSolverConfig.xml&quot;, ScheduleSolverManager.class.getClassLoader());
rosterScoreDirectorFactory = rosterSolverFactory.buildSolver().getScoreDirectorFactory();
}
public CountDownLatch solve(Integer deptID){
final CountDownLatch solvingEndedLatch = new CountDownLatch(1);
try{
taskExecutor.execute(()-&gt;{
Solver&lt;Roster&gt; rosterSolver = rosterSolverFactory.buildSolver();
deptIdToSolverMap.put(deptID, rosterSolver);
rosterSolver.addEventListener(event -&gt; {
if(event.isEveryProblemFactChangeProcessed()){
logger.info(&quot;New best solution found for deptId ({}).&quot;, 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(&quot;Error solving for deptId (&quot; + deptID + &quot;).&quot;, e);
}
return solvingEndedLatch;
}
public Roster getRoster(final Integer deptId){
Solver&lt;Roster&gt; rosterSolver = deptIdToSolverMap.get(deptId);
return rosterSolver == null ? null : rosterSolver.getBestSolution();
}
public ScoreDirector&lt;Roster&gt; getScoreDirector() {
return rosterScoreDirectorFactory.buildScoreDirector();
}
}

The error when run is as follows:
<pre>
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).
</pre>

答案1

得分: 1

使用 optaplanner-spring-boot-starter 它大大简化了与 Spring 的集成。

指南:https://github.com/spring-guides/getting-started-guides/pull/126

视频:https://www.youtube.com/watch?v=U2N02ReT9CI

如果您不想使用这个启动器,这段代码可能会修复:SolverFactory.createFromXmlResource(&quot;com/schedule/demo/service/solver/scheduleSolverConfig.xml&quot;, Roster.class.getClassLoader());(使用 Roster 的类加载器)。

英文:

Use the optaplanner-spring-boot-starter. It simplifies Spring integration greatly.

Guide: https://github.com/spring-guides/getting-started-guides/pull/126

Video: https://www.youtube.com/watch?v=U2N02ReT9CI

If you don't want to use the starter, this code might fix it: SolverFactory.createFromXmlResource(&quot;com/schedule/demo/service/solver/scheduleSolverConfig.xml&quot;, Roster.class.getClassLoader()); (uses the classloader of Roster).

答案2

得分: 1

你必须将求解器配置的 XML 文件放置在 src/main/resources 下,以便能够将其作为类路径资源进行加载。

因此,如果您使用资源名称 com/schedule/demo/service/solver/scheduleSolverConfig.xml 进行加载,那么该文件必须位于以下位置:

src/main/resources/com/schedule/demo/service/solver/scheduleSolverConfig.xml
英文:

You have to place the solver config XML under src/main/resources in order to be able to load it as a classpath resource.

So, if you load it using the resource name com/schedule/demo/service/solver/scheduleSolverConfig.xml, then the file has to be located at

src/main/resources/com/schedule/demo/service/solver/scheduleSolverConfig.xml

huangapple
  • 本文由 发表于 2020年4月6日 22:27:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/61062103.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定