Недопустимое исключение аргумента для проекта Optaplanner, конфигурация решателя не существует как ресурс пути к классам в загрузчике классов - PullRequest
0 голосов
/ 06 апреля 2020

Я получаю сообщение об ошибке при запуске приложения SpringBoot в моем классе решателя. Я пытаюсь создать фабрику решателя из ресурса xml, содержащегося в папке ресурсов, точно так же, как пример составления списка сотрудников для OptaPlanner, но я получаю исключение недопустимого аргумента, которое я не могу понять, почему. Я попытался переместить файл xml в ту же папку, что и класс решателя, но появляется та же ошибка. Я не знаю, почему возникает исключение, когда я следую примеру кода, который OptaPlanner имеет для составления списка сотрудников?

Ниже приведен мой код для моего класса решателя:

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

Ошибка при запуске выглядит следующим образом:

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).

Ответы [ 2 ]

1 голос
/ 07 апреля 2020

Вы должны поместить конфигурацию решателя XML в src/main/resources, чтобы иметь возможность загрузить его как ресурс classpath.

Итак, если вы загружаете его, используя имя ресурса com/schedule/demo/service/solver/scheduleSolverConfig.xml, тогда файл должен находиться в

src/main/resources/com/schedule/demo/service/solver/scheduleSolverConfig.xml
1 голос
/ 07 апреля 2020

Использование optaplanner-spring-boot-starter. Это значительно упрощает интеграцию Spring.

Руководство: https://github.com/spring-guides/getting-started-guides/pull/126

Видео: https://www.youtube.com/watch?v=U2N02ReT9CI

Если вы не хотите использовать стартер, этот код может исправить это: SolverFactory.createFromXmlResource("com/schedule/demo/service/solver/scheduleSolverConfig.xml", Roster.class.getClassLoader()); (использует загрузчик классов Roster).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...