OptaPlanner logo
  • Download
  • Learn
    • Documentation
    • Videos

    • Use cases
    • Compatibility
    • Testimonials and case studies
  • Get help
  • Blog
  • Source
  • Team
  • Services
  • Star
  • T
  • L
  • F
  • YT
Fork me on GitHub

Upgrade recipe 6.4

OptaPlanner’s public API classes are backwards compatible (per series), but users often also use impl classes (which are documented in the reference manual too). This upgrade recipe minimizes the pain to upgrade your code and to take advantage of the newest features in OptaPlanner 8.

Legend

Every upgrade note has an indication how likely your code will be affected by that change:

  • Major Likely to affect your code.
  • Minor Unlikely to affect your code (especially if you followed the examples), unless you have hacks.
  • Impl detail Will not affect your code, unless you have very deep hacks.
  • Recommended Not a backward incompatible change, but you probably want to do this.
  • Readme Read this to better understand why the subsequent major changes were made.
  • Automated Can be applied automatically using our migration tooling.

Upgrade from an older version

To upgrade from an older version, first apply the previous upgrade recipes. You will find the order of migration steps bellow:

Note for Red Hat Decision Manager customers

The RHDM version differs from the OptaPlanner version:

RHDM version OptaPlanner version
7.8 7.39
7.9 7.44
7.1 7.48
7.11 8.5 (and 7.52)
7.12 8.11 (and 7.59)
7.13 8.13 (and 7.67)

Automatic upgrade to the latest version

Update your code in seconds, with optaplanner-migration (an OpenRewrite recipe). Try it:

  1. Stash any local changes.
  2. Run this command in your project directory:
    mvn clean org.openrewrite.maven:rewrite-maven-plugin:LATEST:run -Drewrite.recipeArtifactCoordinates=org.optaplanner:optaplanner-migration:8.35.0.Final -Drewrite.activeRecipes=org.optaplanner.migration.ToLatest

    Note: The -Drewrite.recipeArtifactCoordinates might not work, use the more verbose pom.xml approach instead.

  3. Check the local changes and commit them.

It only does upgrade steps with an Automated badge.

From 6.3.0.Final to 6.4.0.Beta1

Custom ScoreDefinition: getLevelLabels() added

If you have a custom ScoreDefinition: that interface has new method getLevelLabels(). AbstractScoreDefinition and AbstractFeasibilityScoreDefinition now expect those levelLabels as a constructor parameter.

Before in *.java:

public class HardSoftScoreDefinition extends AbstractFeasibilityScoreDefinition<HardSoftScore> {
    public HardSoftScoreDefinition() {}
    public int getLevelsSize() {
        return 2;
    }
    ...
}

After in *.java:

public class HardSoftScoreDefinition extends AbstractFeasibilityScoreDefinition<HardSoftScore> {
    public HardSoftScoreDefinition() {
        super(new String[]{"hard score", "soft score"});
    }
    ...
}

SolutionFileIO: moved to another jar

If you’re using SolutionFileIO: that class has been moved from the optaplanner-benchmark jar to optaplanner-persistence-common jar.

After in pom.xml:

<dependency>
  <groupId>org.optaplanner</groupId>
  <artifactId>optaplanner-persistence-common</artifactId>
</dependency>

XStreamScoreConverter: moved to another jar

If you’re using XStreamScoreConverter: that class has been moved from the optaplanner-benchmark jar to optaplanner-persistence-xstream jar.

After in pom.xml:

<dependency>
  <groupId>org.optaplanner</groupId>
  <artifactId>optaplanner-persistence-xstream</artifactId>
</dependency>

BendableScore and XStream: XStreamBendableScoreConverter replaced

If you’re using BendableScore and XStream: XStreamBendableScoreConverter (which only supported BendableScore) has been deleted. The generic XStreamScoreConverter now supports BendableScore, BendableLongScore and BendableBigDecimalScore too.

Before in *.java:

@XStreamConverter(value = XStreamBendableScoreConverter.class, ints = {1, 2})
private BendableScore score;

After in *.java:

@XStreamConverter(value = XStreamScoreConverter.class, types = {BendableScoreDefinition.class}, ints = {1, 2})
private BendableScore score;

Custom ScoreDefinition: fromLevelNumbers() added

If you have a custom ScoreDefinition: that interface has another new method fromLevelNumbers(). It does the opposite of Score.toLevelNumbers().

After in *.java:

public class HardSoftScoreDefinition extends AbstractFeasibilityScoreDefinition<HardSoftScore> {
    ...
    @Override
    public HardSoftScore fromLevelNumbers(Number[] levelNumbers) {
        if (levelNumbers.length != getLevelsSize()) {
            throw new IllegalStateException("The levelNumbers (" + Arrays.toString(levelNumbers)
                    + ")'s length (" + levelNumbers.length + ") must equal the levelSize (" + getLevelsSize() + ").");
        }
        return HardSoftScore.valueOf((Integer) levelNumbers[0], (Integer) levelNumbers[1]);
    }
}

JPA-Hibernate with OptaPlanner: use new jar

If you’re using JPA-Hibernate with OptaPlanner, you’ll want to take advantage of the new jar optaplanner-persistence-jpa. See docs chapter "Integration" for more information.

Custom Benchmarker ranking: SingleBenchmarkResult methods renamed

If you’re using SingleBenchmarkResult: the functionality of the method getScore() and getUninitializedVariableCount() has moved to getAverageScore() and getAverageUninitializedVariableCount() because of the addition of SubSingleBenchmarkResult (Statistical benchmarking).

Before in *.java:

singleBenchmarkResult.getScore();
singleBenchmarkResult.getUninitializedVariableCount();

After in *.java:

singleBenchmarkResult.getAverageScore();
singleBenchmarkResult.getAverageUninitializedVariableCount();

Every SingleStatistic class: renamed

If you’re using SingleStatistic or any of its subclasses: all of them were renamed to include "Sub" as a part of Statistical benchmarking. The package org.optaplanner.benchmark.impl.statistic.single was also renamed to org.optaplanner.benchmark.impl.statistic.subsingle. SingleStatisticType has not been changed, therefore no changes in the configuration are needed.

Before in *.java:

import org.optaplanner.benchmark.impl.statistic.bestscore.BestScoreSingleStatistic;
...

    BestScoreSingleStatistic singleStatistic;

After in *.java:

import org.optaplanner.benchmark.impl.statistic.bestscore.BestScoreSubSingleStatistic;
...

    BestScoreSubSingleStatistic subSingleStatistic;

Configure SolverFactory per request: use cloneSolverFactory()

If you’re configuring the SolverFactory dynamically for each user request with differ settings, use SolverFactory.cloneSolverFactory() to avoid a race condition.

TerminationConfig: clone() removed

The method TerminationConfig.clone() has been removed. The inherit() method now guarantees that afterwards changing the child or parent will not affect the other.

Before in *.java:

TerminationConfig clone = terminationConfig.clone();

After in *.java:

TerminationConfig clone = new TerminationConfig();
clone.inherit(terminationConfig);

SwingUtils and SwingUncaughtExceptionHandler: moved

If you’ve copy pasted the examples Swing UI, you might be using SwingUtils and SwingUncaughtExceptionHandler. These classes are now in a different package (in the same jar for now).

Before in *.java:

import org.optaplanner.benchmark.impl.aggregator.swingui.SwingUncaughtExceptionHandler;
import org.optaplanner.benchmark.impl.aggregator.swingui.SwingUtils;

After in *.java:

import org.optaplanner.swing.impl.SwingUncaughtExceptionHandler;
import org.optaplanner.swing.impl.SwingUtils;

TangoColorFactory: moved

The class TangoColorFactory has moved to a different package and from optaplanner-examples into optaplanner-benchmark.

Before in *.java:

import org.optaplanner.examples.common.swingui.TangoColorFactory;

After in *.java:

import org.optaplanner.swing.impl.TangoColorFactory;

SolverFactory and Solver: added optional generic type parameter

To avoid the awkward cast to your Solution implementation, both SolverFactory and Solver now optionally support a generic type parameter.

Before in *.java:

    SolverFactory solverFactory = SolverFactory.createFromXmlResource(
            "org/.../cloudBalancingSolverConfig.xml");
    Solver solver = solverFactory.buildSolver();
    solver.solve(unsolvedCloudBalance);
    CloudBalance solvedCloudBalance = (CloudBalance) solver.getBestSolution();

After in *.java:

    SolverFactory<CloudBalance> solverFactory = SolverFactory.createFromXmlResource(
            "org/.../cloudBalancingSolverConfig.xml");
    Solver<CloudBalance> solver = solverFactory.buildSolver();
    solver.solve(unsolvedCloudBalance);
    CloudBalance solvedCloudBalance = solver.getBestSolution();

The old code still works too, because this is part of the public API which is backwards compatible.

Solver: solve() method returns the best solution

The solve() method now returns the best solution, in which case calling getBestSolution() is no longer needed:

Before in *.java:

    solver.solve(unsolvedCloudBalance);
    CloudBalance solvedCloudBalance = solver.getBestSolution();

After in *.java:

    CloudBalance solvedCloudBalance = solver.solve(unsolvedCloudBalance);

The old code still works too, because this is part of the public API which is backwards compatible.

CustomPhaseCommand: new method applyCustomProperties() added

The CustomPhaseCommand has a new method applyCustomProperties() to allow custom properties to be defined in the solver configuration. Instead of implementing that method, you can also extend the new abstract class AbstractCustomPhaseCommand which implements CustomPhaseCommand and implements that method to do nothing (except a validation check).

Before in *.java:

public class ToOriginalMachineSolutionInitializer implements CustomPhaseCommand {
    ...
}

After in *.java:

public class ToOriginalMachineSolutionInitializer extends AbstractCustomPhaseCommand {
    ...
}

[.upgrade-recipe-readme] KieContainer and kjar support for Solver

OptaPlanner now supports kjars, to consume a kjar produced by OptaPlanner Workbench or to deploy a kjar to OptaPlanner Execution Server.

If you need to load a solver configuration or score rules that change more often than your application is released, take a look at the reference manual and SolverFactory.createFromKieContainerXmlResource(…​).

From 6.4.0.Beta1 to 6.4.0.CR1

Thread interruption is now detected

If the thread that called Solver.solve(…​) is interrupted, the solver now terminates early. This ensures a graceful shutdown of each solver when shutdownNow() is called on an ExecutorService of solvers.

Latest release
  • 8.35.0.Final released
    Fri 3 March 2023
Upcoming events
    Add event / Archive
Latest blog posts
  • OptaPlanner 9 is coming
    Tue 21 February 2023
    Lukáš Petrovický
  • Farewell - a new lead
    Tue 15 November 2022
    Geoffrey De Smet
  • Run OptaPlanner workloads on OpenShift, part II
    Wed 9 November 2022
    Radovan Synek
  • Bavet - A faster score engine for OptaPlanner
    Tue 6 September 2022
    Geoffrey De Smet
  • Run OptaPlanner workloads on OpenShift, part I.
    Thu 9 June 2022
    Radovan Synek
  • OptaPlanner deprecates score DRL
    Thu 26 May 2022
    Lukáš Petrovický
  • Real-time planning meets SolverManager
    Mon 7 March 2022
    Radovan Synek
  • Blog archive
Latest videos
  • The Vehicle Routing Problem
    Fri 23 September 2022
    Geoffrey De Smet
  • Introduction to OptaPlanner AI constraint solver
    Thu 25 August 2022
    Anna Dupliak
  • On schedule: Artificial Intelligence plans that meet expectations
    Sat 23 July 2022
    Geoffrey De Smet
  • Host your OptaPlanner app on OpenShift (Kubernetes)
    Mon 7 February 2022
    Geoffrey De Smet
  • OptaPlanner - A fast, easy-to-use, open source AI constraint solver for software developers
    Mon 31 January 2022
  • Order picking planning with OptaPlanner
    Fri 31 December 2021
    Anna Dupliak
  • AI lesson scheduling on Quarkus with OptaPlanner
    Thu 18 November 2021
    Geoffrey De Smet
  • Video archive

OptaPlanner is open. All dependencies of this project are available under the Apache Software License 2.0 or a compatible license. OptaPlanner is trademarked.

This website was built with JBake and is open source.

Community

  • Blog
  • Get Help
  • Team
  • Governance
  • Academic research

Code

  • Build from source
  • Issue tracker
  • Release notes
  • Upgrade recipes
  • Logo and branding
CC by 3.0 | Privacy Policy
Sponsored by Red Hat