diff --git a/core/src/main/java/module-info.java b/core/src/main/java/module-info.java index 8456e1a915..10ad6fb09e 100644 --- a/core/src/main/java/module-info.java +++ b/core/src/main/java/module-info.java @@ -43,6 +43,7 @@ exports ai.timefold.solver.core.config.heuristic.selector.move.factory; exports ai.timefold.solver.core.config.heuristic.selector.move.generic; exports ai.timefold.solver.core.config.heuristic.selector.move.generic.list; + exports ai.timefold.solver.core.config.heuristic.selector.move.generic.list.kopt; exports ai.timefold.solver.core.config.heuristic.selector.value; exports ai.timefold.solver.core.config.localsearch; exports ai.timefold.solver.core.config.localsearch.decider.acceptor; @@ -98,8 +99,6 @@ to ai.timefold.solver.quarkus.deployment, ai.timefold.solver.quarkus; exports ai.timefold.solver.core.impl.domain.common to ai.timefold.solver.quarkus.deployment; - exports ai.timefold.solver.core.impl.domain.common.accessor.gizmo - to ai.timefold.solver.quarkus.deployment; exports ai.timefold.solver.core.impl.domain.entity.descriptor to ai.timefold.solver.jackson, ai.timefold.solver.jaxb, ai.timefold.solver.benchmark, ai.timefold.solver.spring.boot.autoconfigure, ai.timefold.solver.quarkus.integration.test, @@ -209,8 +208,9 @@ exports ai.timefold.solver.core.impl.solver.event to ai.timefold.solver.enterprise.core; // Broad impl usage - exports ai.timefold.solver.core.impl.io.jaxb; + exports ai.timefold.solver.core.impl.domain.common.accessor.gizmo; exports ai.timefold.solver.core.impl.domain.solution.descriptor; + exports ai.timefold.solver.core.impl.io.jaxb; exports ai.timefold.solver.core.impl.solver.termination; // Open configs to JAXB @@ -231,6 +231,8 @@ opens ai.timefold.solver.core.config.heuristic.selector.move.factory to jakarta.xml.bind, org.glassfish.jaxb.runtime; opens ai.timefold.solver.core.config.heuristic.selector.move.generic to jakarta.xml.bind, org.glassfish.jaxb.runtime; opens ai.timefold.solver.core.config.heuristic.selector.move.generic.list to jakarta.xml.bind, org.glassfish.jaxb.runtime; + opens ai.timefold.solver.core.config.heuristic.selector.move.generic.list.kopt + to jakarta.xml.bind, org.glassfish.jaxb.runtime; opens ai.timefold.solver.core.config.heuristic.selector.value to jakarta.xml.bind, org.glassfish.jaxb.runtime; opens ai.timefold.solver.core.config.localsearch to jakarta.xml.bind, org.glassfish.jaxb.runtime; opens ai.timefold.solver.core.config.localsearch.decider.acceptor to jakarta.xml.bind, org.glassfish.jaxb.runtime; @@ -255,4 +257,5 @@ requires org.jspecify; requires org.slf4j; requires io.quarkus.gizmo2; + } \ No newline at end of file diff --git a/docs/src/modules/ROOT/pages/integration/integration.adoc b/docs/src/modules/ROOT/pages/integration/integration.adoc index 0974de8f19..a9c49d8709 100644 --- a/docs/src/modules/ROOT/pages/integration/integration.adoc +++ b/docs/src/modules/ROOT/pages/integration/integration.adoc @@ -993,9 +993,11 @@ class Resource { [#integrationWithJPMS] === Java platform module system (Jigsaw) -When using Timefold Solver from code on the modulepath (Java 9 and higher), -_open_ your packages that contain your domain objects, constraints and solver configuration -_to all modules_ in your `module-info.java` file: +Starting in version 2.0, Timefold Solver has official support for the https://openjdk.org/projects/jigsaw/spec/[Java Platform Module System (JPMS)]. + +When using Timefold Solver from code on the modulepath, +_export_ the packages that contain your domain objects, constraints and solver configuration, and _open_ them to the Timefold Solver module(s) +in your `module-info.java` file: [source,java,options="nowrap"] ---- @@ -1003,13 +1005,32 @@ module org.acme.vehiclerouting { requires ai.timefold.solver.core; ... - opens org.acme.vehiclerouting.domain; // Domain classes - opens org.acme.vehiclerouting.solver; // Constraints + exports org.acme.vehiclerouting.domain; // Domain classes + exports org.acme.vehiclerouting.solver; // Constraints + + opens org.acme.vehiclerouting.domain to ai.timefold.solver.core; // Domain classes + opens org.acme.vehiclerouting.solver to ai.timefold.solver.core; // Constraints ... } ---- -Otherwise Timefold Solver can't reach those classes or files, even if they are exported. +If this is not set up correctly, you will get errors. Usually, these mention the `unnamed module` and give detailed information of what needs to be changed. + +[source,options="nowrap"] +---- +class org.acme.schooltimetabling.domain.Timetable$Timefold$MemberAccessor$Field$lessons (in unnamed module @0x273444fe) +cannot access class org.acme.schooltimetabling.domain.Timetable (in module hello.world.school.timetabling) +because module hello.world.school.timetabling does not export org.acme.schooltimetabling.domain to unnamed module @0x273444fe +---- + +[WARNING] +==== +Only JPMS exported packages are part of the supported public API. +==== +If you access non-exported classes (for example by running on the classpath), and we later change or remove them, we will not treat that as a breaking change. +Those classes are not covered by compatibility guarantees. + +You can opt-out of JPMS by running all JAR files on the classpath instead of using the module path (for example, by not configuring a module path in your build or runtime setup). [#integrationWithHumanPlanners] diff --git a/persistence/jackson/src/main/java/module-info.java b/persistence/jackson/src/main/java/module-info.java index 8def882aa4..2477ae95dc 100644 --- a/persistence/jackson/src/main/java/module-info.java +++ b/persistence/jackson/src/main/java/module-info.java @@ -1,12 +1,14 @@ module ai.timefold.solver.jackson { + exports ai.timefold.solver.jackson.api; provides tools.jackson.databind.JacksonModule with ai.timefold.solver.jackson.api.TimefoldJacksonModule; - requires ai.timefold.solver.core; + requires transitive ai.timefold.solver.core; requires org.jspecify; requires tools.jackson.databind; uses tools.jackson.databind.JacksonModule; + } \ No newline at end of file diff --git a/persistence/jaxb/src/main/java/module-info.java b/persistence/jaxb/src/main/java/module-info.java index 7496205975..54131a1131 100644 --- a/persistence/jaxb/src/main/java/module-info.java +++ b/persistence/jaxb/src/main/java/module-info.java @@ -1,7 +1,8 @@ module ai.timefold.solver.jaxb { + exports ai.timefold.solver.jaxb.api.score; - requires ai.timefold.solver.core; + requires transitive ai.timefold.solver.core; requires jakarta.xml.bind; } \ No newline at end of file diff --git a/persistence/jpa/src/main/java/module-info.java b/persistence/jpa/src/main/java/module-info.java index dace4a9b62..5c1ac0728a 100644 --- a/persistence/jpa/src/main/java/module-info.java +++ b/persistence/jpa/src/main/java/module-info.java @@ -1,6 +1,8 @@ module ai.timefold.solver.jpa { - requires jakarta.persistence; - requires ai.timefold.solver.core; exports ai.timefold.solver.jpa.api.score; + + requires transitive ai.timefold.solver.core; + requires jakarta.persistence; + } \ No newline at end of file diff --git a/quarkus-integration/quarkus-benchmark/deployment/src/main/java/module-info.java b/quarkus-integration/quarkus-benchmark/deployment/src/main/java/module-info.java index 7bf6d12453..453481f90c 100644 --- a/quarkus-integration/quarkus-benchmark/deployment/src/main/java/module-info.java +++ b/quarkus-integration/quarkus-benchmark/deployment/src/main/java/module-info.java @@ -4,15 +4,13 @@ exports ai.timefold.solver.benchmark.quarkus.deployment to ai.timefold.solver.enterprise.quarkus.deployment; - requires ai.timefold.solver.benchmark; - requires ai.timefold.solver.core; requires ai.timefold.solver.quarkus.benchmark; + requires ai.timefold.solver.quarkus.deployment; requires io.smallrye.config; requires org.jboss.logging; requires quarkus.arc.deployment; requires quarkus.builder; requires quarkus.core; requires quarkus.core.deployment; - requires ai.timefold.solver.quarkus.deployment; } \ No newline at end of file diff --git a/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/module-info.java b/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/module-info.java index c69ac3a289..61ac683196 100644 --- a/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/module-info.java +++ b/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/module-info.java @@ -1,7 +1,6 @@ module ai.timefold.solver.quarkus.benchmark.integration.test { - requires ai.timefold.solver.core; - requires ai.timefold.solver.benchmark; + requires ai.timefold.solver.quarkus.benchmark; requires jakarta.inject; requires jakarta.ws.rs; requires org.jspecify; diff --git a/quarkus-integration/quarkus-benchmark/runtime/src/main/java/module-info.java b/quarkus-integration/quarkus-benchmark/runtime/src/main/java/module-info.java index 44f17277ff..e538b86b9f 100644 --- a/quarkus-integration/quarkus-benchmark/runtime/src/main/java/module-info.java +++ b/quarkus-integration/quarkus-benchmark/runtime/src/main/java/module-info.java @@ -3,9 +3,8 @@ exports ai.timefold.solver.benchmark.quarkus; exports ai.timefold.solver.benchmark.quarkus.config; - requires ai.timefold.solver.benchmark; - requires ai.timefold.solver.core; - requires ai.timefold.solver.quarkus; + requires transitive ai.timefold.solver.benchmark; + requires transitive ai.timefold.solver.quarkus; requires arc; requires io.smallrye.config; requires jakarta.cdi; diff --git a/quarkus-integration/quarkus-jackson/deployment/src/main/java/module-info.java b/quarkus-integration/quarkus-jackson/deployment/src/main/java/module-info.java index ed0cae68dd..eef3e03613 100644 --- a/quarkus-integration/quarkus-jackson/deployment/src/main/java/module-info.java +++ b/quarkus-integration/quarkus-jackson/deployment/src/main/java/module-info.java @@ -1,6 +1,10 @@ module ai.timefold.solver.quarkus.jackson.deployment { + + exports ai.timefold.solver.quarkus.jackson.deployment; + + requires transitive ai.timefold.solver.quarkus.jackson; + requires quarkus.core; requires quarkus.core.deployment; requires quarkus.jackson.spi; - requires ai.timefold.solver.quarkus.jackson; - requires quarkus.core; + } \ No newline at end of file diff --git a/quarkus-integration/quarkus-jackson/integration-test/src/main/java/module-info.java b/quarkus-integration/quarkus-jackson/integration-test/src/main/java/module-info.java index 90b8883a92..6579cf9b67 100644 --- a/quarkus-integration/quarkus-jackson/integration-test/src/main/java/module-info.java +++ b/quarkus-integration/quarkus-jackson/integration-test/src/main/java/module-info.java @@ -1,6 +1,8 @@ module ai.timefold.solver.quarkus.jackson.integration.test { - requires ai.timefold.solver.core; + + requires ai.timefold.solver.quarkus.jackson; requires jakarta.inject; requires jakarta.ws.rs; requires org.jspecify; + } \ No newline at end of file diff --git a/quarkus-integration/quarkus-jackson/runtime/src/main/java/module-info.java b/quarkus-integration/quarkus-jackson/runtime/src/main/java/module-info.java index 6e3cb6592d..373bacfa6a 100644 --- a/quarkus-integration/quarkus-jackson/runtime/src/main/java/module-info.java +++ b/quarkus-integration/quarkus-jackson/runtime/src/main/java/module-info.java @@ -1,7 +1,9 @@ module ai.timefold.solver.quarkus.jackson { + exports ai.timefold.solver.quarkus.jackson; - requires ai.timefold.solver.core; + requires transitive ai.timefold.solver.core; requires com.fasterxml.jackson.databind; requires org.jspecify; + } \ No newline at end of file diff --git a/quarkus-integration/quarkus/deployment/src/main/java/module-info.java b/quarkus-integration/quarkus/deployment/src/main/java/module-info.java index 3a94ef46bd..e22327af1a 100644 --- a/quarkus-integration/quarkus/deployment/src/main/java/module-info.java +++ b/quarkus-integration/quarkus/deployment/src/main/java/module-info.java @@ -10,21 +10,20 @@ ai.timefold.solver.quarkus.benchmark.deployment, ai.timefold.sdk.quarkus.deployment; - requires ai.timefold.solver.quarkus; - requires quarkus.arc.deployment; - requires quarkus.builder; - requires quarkus.core.deployment; - requires quarkus.devui.deployment.spi; - requires ai.timefold.solver.core; - requires io.quarkus.gizmo2; - requires jakarta.cdi; - requires quarkus.core; + requires transitive ai.timefold.solver.quarkus; requires arc.processor; - requires org.jspecify; requires io.quarkus.gizmo; - requires org.jboss.jandex; + requires io.quarkus.gizmo2; requires io.smallrye.config; - requires org.objectweb.asm; + requires jakarta.cdi; + requires org.jboss.jandex; requires org.jboss.logging; + requires org.jspecify; + requires org.objectweb.asm; + requires quarkus.arc.deployment; + requires quarkus.builder; + requires quarkus.core; + requires quarkus.core.deployment; + requires quarkus.devui.deployment.spi; } \ No newline at end of file diff --git a/quarkus-integration/quarkus/devui-integration-test/src/main/java/module-info.java b/quarkus-integration/quarkus/devui-integration-test/src/main/java/module-info.java index 49e9c0433a..a2e4460a38 100644 --- a/quarkus-integration/quarkus/devui-integration-test/src/main/java/module-info.java +++ b/quarkus-integration/quarkus/devui-integration-test/src/main/java/module-info.java @@ -1,4 +1,6 @@ module ai.timefold.solver.quarkus.devui.integration.test { - requires ai.timefold.solver.core; + + requires ai.timefold.solver.quarkus; requires org.jspecify; + } \ No newline at end of file diff --git a/quarkus-integration/quarkus/integration-test/src/main/java/module-info.java b/quarkus-integration/quarkus/integration-test/src/main/java/module-info.java index a123ebdef7..30ea953b42 100644 --- a/quarkus-integration/quarkus/integration-test/src/main/java/module-info.java +++ b/quarkus-integration/quarkus/integration-test/src/main/java/module-info.java @@ -1,6 +1,8 @@ module ai.timefold.solver.quarkus.integration.test { - requires ai.timefold.solver.core; + + requires ai.timefold.solver.quarkus; requires jakarta.inject; requires jakarta.ws.rs; requires org.jspecify; + } \ No newline at end of file diff --git a/quarkus-integration/quarkus/reflection-integration-test/src/main/java/module-info.java b/quarkus-integration/quarkus/reflection-integration-test/src/main/java/module-info.java index 61acd4909b..392ba78ee4 100644 --- a/quarkus-integration/quarkus/reflection-integration-test/src/main/java/module-info.java +++ b/quarkus-integration/quarkus/reflection-integration-test/src/main/java/module-info.java @@ -1,6 +1,8 @@ module ai.timefold.solver.quarkus.reflection.integration.test { - requires ai.timefold.solver.core; + + requires ai.timefold.solver.quarkus; requires jakarta.inject; requires jakarta.ws.rs; requires org.jspecify; + } \ No newline at end of file diff --git a/quarkus-integration/quarkus/runtime/src/main/java/module-info.java b/quarkus-integration/quarkus/runtime/src/main/java/module-info.java index 16ada9da6f..a5dabcf563 100644 --- a/quarkus-integration/quarkus/runtime/src/main/java/module-info.java +++ b/quarkus-integration/quarkus/runtime/src/main/java/module-info.java @@ -1,21 +1,21 @@ module ai.timefold.solver.quarkus { - exports ai.timefold.solver.quarkus.bean; exports ai.timefold.solver.quarkus; + exports ai.timefold.solver.quarkus.bean; exports ai.timefold.solver.quarkus.config; exports ai.timefold.solver.quarkus.devui; exports ai.timefold.solver.quarkus.gizmo; - requires ai.timefold.solver.core; + requires transitive ai.timefold.solver.core; requires arc; + requires io.smallrye.config; requires io.vertx.core; requires jakarta.cdi; requires jakarta.inject; + requires org.eclipse.microprofile.config; requires org.graalvm.nativeimage; + requires org.jboss.logging; requires org.jspecify; requires quarkus.core; - requires io.smallrye.config; - requires org.jboss.logging; - requires org.eclipse.microprofile.config; } \ No newline at end of file diff --git a/spring-integration/spring-boot-autoconfigure/src/main/java/module-info.java b/spring-integration/spring-boot-autoconfigure/src/main/java/module-info.java index fea246c207..018c654090 100644 --- a/spring-integration/spring-boot-autoconfigure/src/main/java/module-info.java +++ b/spring-integration/spring-boot-autoconfigure/src/main/java/module-info.java @@ -1,6 +1,16 @@ module ai.timefold.solver.spring.boot.autoconfigure { - requires ai.timefold.solver.jackson; + + exports ai.timefold.solver.spring.boot.autoconfigure; + exports ai.timefold.solver.spring.boot.autoconfigure.config; + exports ai.timefold.solver.spring.boot.autoconfigure.util; + + opens ai.timefold.solver.spring.boot.autoconfigure; + + requires static ai.timefold.solver.benchmark; + requires transitive ai.timefold.solver.core; + requires transitive ai.timefold.solver.jackson; requires org.apache.commons.logging; + requires org.jspecify; requires spring.beans; requires spring.boot; requires spring.boot.autoconfigure; @@ -8,7 +18,5 @@ requires spring.context; requires spring.core; requires tools.jackson.databind; - requires ai.timefold.solver.benchmark; - requires ai.timefold.solver.core; - requires org.jspecify; + } \ No newline at end of file diff --git a/spring-integration/spring-boot-integration-test/src/main/java/module-info.java b/spring-integration/spring-boot-integration-test/src/main/java/module-info.java index a002a95c56..4821f748fc 100644 --- a/spring-integration/spring-boot-integration-test/src/main/java/module-info.java +++ b/spring-integration/spring-boot-integration-test/src/main/java/module-info.java @@ -1,7 +1,9 @@ module ai.timefold.solver.spring.boot.integration.test { - requires ai.timefold.solver.core; + + requires ai.timefold.solver.spring.boot.starter; requires org.jspecify; requires spring.boot; requires spring.boot.autoconfigure; requires spring.web; + } \ No newline at end of file diff --git a/spring-integration/spring-boot-starter/src/main/java/module-info.java b/spring-integration/spring-boot-starter/src/main/java/module-info.java index 705c5b3e34..173a182b2a 100644 --- a/spring-integration/spring-boot-starter/src/main/java/module-info.java +++ b/spring-integration/spring-boot-starter/src/main/java/module-info.java @@ -1,5 +1,5 @@ module ai.timefold.solver.spring.boot.starter { - requires ai.timefold.solver.spring.boot.autoconfigure; + requires transitive ai.timefold.solver.spring.boot.autoconfigure; } \ No newline at end of file diff --git a/tools/benchmark/src/main/java/module-info.java b/tools/benchmark/src/main/java/module-info.java index 9769c2dea4..712a3f0cfc 100644 --- a/tools/benchmark/src/main/java/module-info.java +++ b/tools/benchmark/src/main/java/module-info.java @@ -1,15 +1,5 @@ module ai.timefold.solver.benchmark { - requires ai.timefold.solver.core; - requires ai.timefold.solver.jaxb; - requires commons.math3; - requires freemarker; - requires jakarta.xml.bind; - requires java.xml; - requires micrometer.core; - requires org.jspecify; - requires org.slf4j; - // Public API exports ai.timefold.solver.benchmark.api; @@ -41,4 +31,14 @@ exports ai.timefold.solver.benchmark.impl to ai.timefold.solver.quarkus.benchmark.integration.test; + requires transitive ai.timefold.solver.core; + requires ai.timefold.solver.jaxb; + requires commons.math3; + requires freemarker; + requires jakarta.xml.bind; + requires java.xml; + requires micrometer.core; + requires org.jspecify; + requires org.slf4j; + } \ No newline at end of file