This is an automated email from the ASF dual-hosted git repository. ppalaga pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit ee56a0606144cc5989186931dca7dab2a1e856d5 Author: Zineb Bendhiba <bendhiba.zi...@gmail.com> AuthorDate: Fri Sep 11 15:56:35 2020 +0200 OptaPlanner native support fixes #1721 --- .../pages/reference/extensions/optaplanner.adoc | 8 +- .../partials/reference/components/optaplanner.adoc | 6 +- extensions-jvm/pom.xml | 1 - .../optaplanner/deployment/pom.xml | 16 +++ .../deployment/OptaplannerProcessor.java | 14 --- {extensions-jvm => extensions}/optaplanner/pom.xml | 1 - .../optaplanner/runtime/pom.xml | 30 ++++++ .../main/resources/META-INF/quarkus-extension.yaml | 3 +- extensions/pom.xml | 1 + .../optaplanner}/pom.xml | 74 ++++++++++++- .../quarkus/component/optaplanner/it/MyBean.java | 48 +++++++++ .../optaplanner/it/OptaplannerResource.java | 89 ++++++++++++++++ .../quarkus/component/optaplanner/it/Routes.java | 39 +++---- .../optaplanner/it/bootstrap/DataGenerator.java | 95 +++++++++++++++++ .../component/optaplanner/it/domain/Lesson.java | 100 +++++++++++++++++ .../component/optaplanner/it/domain/Room.java | 61 +++++++++++ .../component/optaplanner/it/domain/TimeTable.java | 72 +++++++++++++ .../component/optaplanner/it/domain/Timeslot.java | 77 ++++++++++++++ .../it/solver/TimeTableConstraintProvider.java | 118 +++++++++++++++++++++ .../src/main/resources/application.properties | 32 ++++++ .../component/optaplanner/it/OptaplannerIT.java | 16 +-- .../component/optaplanner/it/OptaplannerTest.java | 31 +++++- integration-tests/pom.xml | 1 + pom.xml | 2 + poms/bom/pom.xml | 10 ++ tooling/scripts/test-categories.yaml | 1 + 26 files changed, 877 insertions(+), 69 deletions(-) diff --git a/docs/modules/ROOT/pages/reference/extensions/optaplanner.adoc b/docs/modules/ROOT/pages/reference/extensions/optaplanner.adoc index bc9def7..d4fa4d3 100644 --- a/docs/modules/ROOT/pages/reference/extensions/optaplanner.adoc +++ b/docs/modules/ROOT/pages/reference/extensions/optaplanner.adoc @@ -2,15 +2,15 @@ // This file was generated by camel-quarkus-maven-plugin:update-extension-doc-page = OptaPlanner :cq-artifact-id: camel-quarkus-optaplanner -:cq-native-supported: false -:cq-status: Preview +:cq-native-supported: true +:cq-status: Stable :cq-description: Solve planning problems with OptaPlanner. :cq-deprecated: false :cq-jvm-since: 1.1.0 -:cq-native-since: n/a +:cq-native-since: 1.2.0 [.badges] -[.badge-key]##JVM since##[.badge-supported]##1.1.0## [.badge-key]##Native##[.badge-unsupported]##unsupported## +[.badge-key]##JVM since##[.badge-supported]##1.1.0## [.badge-key]##Native since##[.badge-supported]##1.2.0## Solve planning problems with OptaPlanner. diff --git a/docs/modules/ROOT/partials/reference/components/optaplanner.adoc b/docs/modules/ROOT/partials/reference/components/optaplanner.adoc index e5a1a6b..4e31fd7 100644 --- a/docs/modules/ROOT/partials/reference/components/optaplanner.adoc +++ b/docs/modules/ROOT/partials/reference/components/optaplanner.adoc @@ -2,11 +2,11 @@ // This file was generated by camel-quarkus-maven-plugin:update-extension-doc-page :cq-artifact-id: camel-quarkus-optaplanner :cq-artifact-id-base: optaplanner -:cq-native-supported: false -:cq-status: Preview +:cq-native-supported: true +:cq-status: Stable :cq-deprecated: false :cq-jvm-since: 1.1.0 -:cq-native-since: n/a +:cq-native-since: 1.2.0 :cq-camel-part-name: optaplanner :cq-camel-part-title: OptaPlanner :cq-camel-part-description: Solve planning problems with OptaPlanner. diff --git a/extensions-jvm/pom.xml b/extensions-jvm/pom.xml index d13fcc5..dbb2244 100644 --- a/extensions-jvm/pom.xml +++ b/extensions-jvm/pom.xml @@ -108,7 +108,6 @@ <module>nitrite</module> <module>ognl</module> <module>openstack</module> - <module>optaplanner</module> <module>printer</module> <module>pubnub</module> <module>pulsar</module> diff --git a/extensions-jvm/optaplanner/deployment/pom.xml b/extensions/optaplanner/deployment/pom.xml similarity index 81% rename from extensions-jvm/optaplanner/deployment/pom.xml rename to extensions/optaplanner/deployment/pom.xml index 1b047be..d2bed0b 100644 --- a/extensions-jvm/optaplanner/deployment/pom.xml +++ b/extensions/optaplanner/deployment/pom.xml @@ -29,6 +29,18 @@ <artifactId>camel-quarkus-optaplanner-deployment</artifactId> <name>Camel Quarkus :: OptaPlanner :: Deployment</name> + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.optaplanner</groupId> + <artifactId>optaplanner-quarkus-deployment</artifactId> + <version>${optaplanner.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + <dependencies> <dependency> <groupId>org.apache.camel.quarkus</groupId> @@ -38,6 +50,10 @@ <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-optaplanner</artifactId> </dependency> + <dependency> + <groupId>org.optaplanner</groupId> + <artifactId>optaplanner-quarkus-deployment</artifactId> + </dependency> </dependencies> <build> diff --git a/extensions-jvm/optaplanner/deployment/src/main/java/org/apache/camel/quarkus/component/optaplanner/deployment/OptaplannerProcessor.java b/extensions/optaplanner/deployment/src/main/java/org/apache/camel/quarkus/component/optaplanner/deployment/OptaplannerProcessor.java similarity index 68% rename from extensions-jvm/optaplanner/deployment/src/main/java/org/apache/camel/quarkus/component/optaplanner/deployment/OptaplannerProcessor.java rename to extensions/optaplanner/deployment/src/main/java/org/apache/camel/quarkus/component/optaplanner/deployment/OptaplannerProcessor.java index d07ab81..3956d43 100644 --- a/extensions-jvm/optaplanner/deployment/src/main/java/org/apache/camel/quarkus/component/optaplanner/deployment/OptaplannerProcessor.java +++ b/extensions/optaplanner/deployment/src/main/java/org/apache/camel/quarkus/component/optaplanner/deployment/OptaplannerProcessor.java @@ -17,11 +17,7 @@ package org.apache.camel.quarkus.component.optaplanner.deployment; import io.quarkus.deployment.annotations.BuildStep; -import io.quarkus.deployment.annotations.ExecutionTime; -import io.quarkus.deployment.annotations.Record; import io.quarkus.deployment.builditem.FeatureBuildItem; -import io.quarkus.deployment.pkg.steps.NativeBuild; -import org.apache.camel.quarkus.core.JvmOnlyRecorder; import org.jboss.logging.Logger; class OptaplannerProcessor { @@ -33,14 +29,4 @@ class OptaplannerProcessor { FeatureBuildItem feature() { return new FeatureBuildItem(FEATURE); } - - /** - * Remove this once this extension starts supporting the native mode. - */ - @BuildStep(onlyIf = NativeBuild.class) - @Record(value = ExecutionTime.RUNTIME_INIT) - void warnJvmInNative(JvmOnlyRecorder recorder) { - JvmOnlyRecorder.warnJvmInNative(LOG, FEATURE); // warn at build time - recorder.warnJvmInNative(FEATURE); // warn at runtime - } } diff --git a/extensions-jvm/optaplanner/pom.xml b/extensions/optaplanner/pom.xml similarity index 97% rename from extensions-jvm/optaplanner/pom.xml rename to extensions/optaplanner/pom.xml index fa0bff5..0e1dede 100644 --- a/extensions-jvm/optaplanner/pom.xml +++ b/extensions/optaplanner/pom.xml @@ -33,6 +33,5 @@ <modules> <module>deployment</module> <module>runtime</module> - <module>integration-test</module> </modules> </project> diff --git a/extensions-jvm/optaplanner/runtime/pom.xml b/extensions/optaplanner/runtime/pom.xml similarity index 77% rename from extensions-jvm/optaplanner/runtime/pom.xml rename to extensions/optaplanner/runtime/pom.xml index ac8340b..5c5fdda 100644 --- a/extensions-jvm/optaplanner/runtime/pom.xml +++ b/extensions/optaplanner/runtime/pom.xml @@ -32,6 +32,7 @@ <properties> <camel.quarkus.jvmSince>1.1.0</camel.quarkus.jvmSince> + <camel.quarkus.nativeSince>1.2.0</camel.quarkus.nativeSince> </properties> <dependencyManagement> @@ -43,6 +44,20 @@ <type>pom</type> <scope>import</scope> </dependency> + <dependency> + <groupId>org.optaplanner</groupId> + <artifactId>optaplanner-quarkus</artifactId> + <version>${optaplanner.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + <dependency> + <groupId>org.mvel</groupId> + <artifactId>mvel2</artifactId> + <version>${mvel2.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> </dependencies> </dependencyManagement> @@ -55,6 +70,21 @@ <groupId>org.apache.camel</groupId> <artifactId>camel-optaplanner</artifactId> </dependency> + <dependency> + <groupId>org.optaplanner</groupId> + <artifactId>optaplanner-quarkus</artifactId> + <exclusions> + <exclusion> + <groupId>org.mvel</groupId> + <artifactId>mvel2</artifactId> + </exclusion> + </exclusions> + </dependency> + <!-- delete mvel2 dependency when optaplanner 7.45.0.Final is released--> + <dependency> + <groupId>org.mvel</groupId> + <artifactId>mvel2</artifactId> + </dependency> </dependencies> <build> diff --git a/extensions-jvm/optaplanner/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/optaplanner/runtime/src/main/resources/META-INF/quarkus-extension.yaml similarity index 97% rename from extensions-jvm/optaplanner/runtime/src/main/resources/META-INF/quarkus-extension.yaml rename to extensions/optaplanner/runtime/src/main/resources/META-INF/quarkus-extension.yaml index 343577a..8951b1f 100644 --- a/extensions-jvm/optaplanner/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/optaplanner/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -24,9 +24,8 @@ name: "Camel OptaPlanner" description: "Solve planning problems with OptaPlanner" metadata: - unlisted: true guide: "https://camel.apache.org/camel-quarkus/latest/reference/extensions/optaplanner.html" categories: - "integration" status: - - "preview" + - "stable" diff --git a/extensions/pom.xml b/extensions/pom.xml index 689c85e..7d7172f 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -164,6 +164,7 @@ <module>olingo4</module> <module>openapi-java</module> <module>opentracing</module> + <module>optaplanner</module> <module>paho</module> <module>pdf</module> <module>pg-replication-slot</module> diff --git a/extensions-jvm/optaplanner/integration-test/pom.xml b/integration-tests/optaplanner/pom.xml similarity index 54% rename from extensions-jvm/optaplanner/integration-test/pom.xml rename to integration-tests/optaplanner/pom.xml index 4b9af27..8b510b3 100644 --- a/extensions-jvm/optaplanner/integration-test/pom.xml +++ b/integration-tests/optaplanner/pom.xml @@ -21,13 +21,12 @@ <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-build-parent-it</artifactId> + <artifactId>camel-quarkus-integration-tests</artifactId> <version>1.5.0-SNAPSHOT</version> - <relativePath>../../../poms/build-parent-it/pom.xml</relativePath> </parent> - <artifactId>camel-quarkus-optaplanner-integration-test</artifactId> - <name>Camel Quarkus :: OptaPlanner :: Integration Test</name> + <artifactId>camel-quarkus-integration-test-optaplanner</artifactId> + <name>Camel Quarkus :: Integration Tests :: OptaPlanner</name> <description>Integration tests for Camel Quarkus OptaPlanner extension</description> <dependencyManagement> @@ -51,6 +50,18 @@ <groupId>io.quarkus</groupId> <artifactId>quarkus-resteasy</artifactId> </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-resteasy-jackson</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-direct</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-bean</artifactId> + </dependency> <!-- test dependencies --> <dependency> @@ -67,6 +78,32 @@ <!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory --> <dependency> <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-bean-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-direct-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-optaplanner-deployment</artifactId> <version>${project.version}</version> <type>pom</type> @@ -80,4 +117,33 @@ </dependency> </dependencies> + <profiles> + <profile> + <id>native</id> + <activation> + <property> + <name>native</name> + </property> + </activation> + <properties> + <quarkus.package.type>native</quarkus.package.type> + </properties> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> </project> diff --git a/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/MyBean.java b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/MyBean.java new file mode 100644 index 0000000..185cda0 --- /dev/null +++ b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/MyBean.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.optaplanner.it; + +import javax.enterprise.context.ApplicationScoped; + +import io.quarkus.runtime.annotations.RegisterForReflection; +import org.apache.camel.Exchange; +import org.apache.camel.component.optaplanner.OptaPlannerConstants; +import org.apache.camel.quarkus.component.optaplanner.it.domain.TimeTable; + +@RegisterForReflection +@ApplicationScoped +public class MyBean { + + public TimeTable bestSolution; + + public TimeTable getBestSolution() { + return bestSolution; + } + + public void setBestSolution(TimeTable bestSolution) { + this.bestSolution = bestSolution; + } + + public void updateBestSolution(Exchange exchange) { + if (exchange != null) { + TimeTable newBestSolution = exchange.getMessage().getHeader(OptaPlannerConstants.BEST_SOLUTION, TimeTable.class); + if (newBestSolution != null) { + this.bestSolution = newBestSolution; + } + } + } +} diff --git a/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerResource.java b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerResource.java new file mode 100644 index 0000000..70f5f9c --- /dev/null +++ b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerResource.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.optaplanner.it; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.apache.camel.ProducerTemplate; +import org.apache.camel.component.optaplanner.OptaPlannerConstants; +import org.apache.camel.quarkus.component.optaplanner.it.bootstrap.DataGenerator; +import org.apache.camel.quarkus.component.optaplanner.it.domain.TimeTable; +import org.jboss.logging.Logger; +import org.optaplanner.core.api.solver.SolverManager; +import org.optaplanner.core.api.solver.SolverStatus; + +@Path("/optaplanner") +@ApplicationScoped +@Produces(MediaType.APPLICATION_JSON) +public class OptaplannerResource { + + private static final Logger LOG = Logger.getLogger(OptaplannerResource.class); + + public static final Long SINGLETON_TIME_TABLE_ID = 1L; + + @Inject + SolverManager<TimeTable, Long> solverManager; + + @Inject + ProducerTemplate producerTemplate; + + @Inject + MyBean bean; + + @GET + @Path("solveSync") + public TimeTable solveSync() { + if (SolverStatus.NOT_SOLVING == solverManager.getSolverStatus(SINGLETON_TIME_TABLE_ID)) { + TimeTable finalSolution = producerTemplate.requestBodyAndHeader( + "direct:solveSync", DataGenerator.timeTable, + OptaPlannerConstants.SOLVER_MANAGER, solverManager, TimeTable.class); + return finalSolution; + } + return DataGenerator.timeTable; + } + + @GET + @Path("solveAsync") + public TimeTable solveAsync() throws ExecutionException, InterruptedException { + // reset best Solution + bean.setBestSolution(null); + if (SolverStatus.NOT_SOLVING == solverManager.getSolverStatus(SINGLETON_TIME_TABLE_ID)) { + CompletableFuture<TimeTable> response = producerTemplate.asyncRequestBodyAndHeader( + "direct:solveAsync", DataGenerator.timeTable, OptaPlannerConstants.SOLVER_MANAGER, + solverManager, TimeTable.class); + + TimeTable finalSolution = response.get(); + return finalSolution; + } + return DataGenerator.timeTable; + } + + @GET + @Path("newBestSolution") + public TimeTable getNewBestSolution() { + return bean.getBestSolution(); + } + +} diff --git a/extensions-jvm/optaplanner/integration-test/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerResource.java b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/Routes.java similarity index 50% rename from extensions-jvm/optaplanner/integration-test/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerResource.java rename to integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/Routes.java index 8c7ae86..8f82b9e 100644 --- a/extensions-jvm/optaplanner/integration-test/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerResource.java +++ b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/Routes.java @@ -18,34 +18,27 @@ package org.apache.camel.quarkus.component.optaplanner.it; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import org.apache.camel.CamelContext; -import org.jboss.logging.Logger; +import org.apache.camel.builder.RouteBuilder; -@Path("/optaplanner") @ApplicationScoped -public class OptaplannerResource { +public class Routes extends RouteBuilder { + @Inject + MyBean bean; - private static final Logger LOG = Logger.getLogger(OptaplannerResource.class); + @Override + public void configure() throws Exception { - private static final String COMPONENT_OPTAPLANNER = "optaplanner"; - @Inject - CamelContext context; + // async producer + from("direct:solveAsync").to("optaplanner:anything?useSolverManager=true&async=true&problemId=" + + OptaplannerResource.SINGLETON_TIME_TABLE_ID); + + // async consumer + from("optaplanner:anything?useSolverManager=true&problemId=" + OptaplannerResource.SINGLETON_TIME_TABLE_ID) + .bean(bean, "updateBestSolution"); - @Path("/load/component/optaplanner") - @GET - @Produces(MediaType.TEXT_PLAIN) - public Response loadComponentOptaplanner() throws Exception { - /* This is an autogenerated test */ - if (context.getComponent(COMPONENT_OPTAPLANNER) != null) { - return Response.ok().build(); - } - LOG.warnf("Could not load [%s] from the Camel context", COMPONENT_OPTAPLANNER); - return Response.status(500, COMPONENT_OPTAPLANNER + " could not be loaded from the Camel context").build(); + // sync producer + from("direct:solveSync") + .to("optaplanner:anything?useSolverManager=true&problemId=" + OptaplannerResource.SINGLETON_TIME_TABLE_ID); } } diff --git a/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/bootstrap/DataGenerator.java b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/bootstrap/DataGenerator.java new file mode 100644 index 0000000..7538aeb --- /dev/null +++ b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/bootstrap/DataGenerator.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.optaplanner.it.bootstrap; + +import java.time.DayOfWeek; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.List; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; + +import io.quarkus.runtime.StartupEvent; +import org.apache.camel.quarkus.component.optaplanner.it.domain.Lesson; +import org.apache.camel.quarkus.component.optaplanner.it.domain.Room; +import org.apache.camel.quarkus.component.optaplanner.it.domain.TimeTable; +import org.apache.camel.quarkus.component.optaplanner.it.domain.Timeslot; + +/** + * adapted from optaplanner quarkus quickstart : + * https://github.com/quarkusio/quarkus-quickstarts/blob/master/optaplanner-quickstart/src/main/java/org/acme/optaplanner/bootstrap/DemoDataGenerator.java + */ +@ApplicationScoped +public class DataGenerator { + + public static List<Timeslot> timeslotList; + + public static List<Room> roomList; + + public static List<Lesson> lessonList; + + public static TimeTable timeTable; + + public void generateDemoData(@Observes StartupEvent startupEvent) { + timeslotList = new ArrayList<>(10); + timeslotList.add(new Timeslot(DayOfWeek.MONDAY, LocalTime.of(8, 30), LocalTime.of(9, 30))); + timeslotList.add(new Timeslot(DayOfWeek.MONDAY, LocalTime.of(9, 30), LocalTime.of(10, 30))); + timeslotList.add(new Timeslot(DayOfWeek.MONDAY, LocalTime.of(10, 30), LocalTime.of(11, 30))); + timeslotList.add(new Timeslot(DayOfWeek.MONDAY, LocalTime.of(13, 30), LocalTime.of(14, 30))); + timeslotList.add(new Timeslot(DayOfWeek.MONDAY, LocalTime.of(14, 30), LocalTime.of(15, 30))); + timeslotList.add(new Timeslot(DayOfWeek.TUESDAY, LocalTime.of(8, 30), LocalTime.of(9, 30))); + timeslotList.add(new Timeslot(DayOfWeek.TUESDAY, LocalTime.of(9, 30), LocalTime.of(10, 30))); + timeslotList.add(new Timeslot(DayOfWeek.TUESDAY, LocalTime.of(10, 30), LocalTime.of(11, 30))); + timeslotList.add(new Timeslot(DayOfWeek.TUESDAY, LocalTime.of(13, 30), LocalTime.of(14, 30))); + timeslotList.add(new Timeslot(DayOfWeek.TUESDAY, LocalTime.of(14, 30), LocalTime.of(15, 30))); + + roomList = new ArrayList<>(3); + roomList.add(new Room("Room A")); + roomList.add(new Room("Room B")); + roomList.add(new Room("Room C")); + + lessonList = new ArrayList<>(); + lessonList.add(new Lesson("Math", "A. Turing", "9th grade")); + lessonList.add(new Lesson("Math", "A. Turing", "9th grade")); + lessonList.add(new Lesson("Physics", "M. Curie", "9th grade")); + lessonList.add(new Lesson("Chemistry", "M. Curie", "9th grade")); + lessonList.add(new Lesson("Biology", "C. Darwin", "9th grade")); + lessonList.add(new Lesson("History", "I. Jones", "9th grade")); + lessonList.add(new Lesson("English", "I. Jones", "9th grade")); + lessonList.add(new Lesson("English", "I. Jones", "9th grade")); + lessonList.add(new Lesson("Spanish", "P. Cruz", "9th grade")); + lessonList.add(new Lesson("Spanish", "P. Cruz", "9th grade")); + + lessonList.add(new Lesson("Math", "A. Turing", "10th grade")); + lessonList.add(new Lesson("Math", "A. Turing", "10th grade")); + lessonList.add(new Lesson("Math", "A. Turing", "10th grade")); + lessonList.add(new Lesson("Physics", "M. Curie", "10th grade")); + lessonList.add(new Lesson("Chemistry", "M. Curie", "10th grade")); + lessonList.add(new Lesson("French", "M. Curie", "10th grade")); + lessonList.add(new Lesson("Geography", "C. Darwin", "10th grade")); + lessonList.add(new Lesson("History", "I. Jones", "10th grade")); + lessonList.add(new Lesson("English", "P. Cruz", "10th grade")); + lessonList.add(new Lesson("Spanish", "P. Cruz", "10th grade")); + + timeTable = new TimeTable( + DataGenerator.timeslotList, + DataGenerator.roomList, + DataGenerator.lessonList); + } + +} diff --git a/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/domain/Lesson.java b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/domain/Lesson.java new file mode 100644 index 0000000..fb7b977 --- /dev/null +++ b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/domain/Lesson.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.optaplanner.it.domain; + +import java.util.concurrent.atomic.AtomicLong; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import org.optaplanner.core.api.domain.entity.PlanningEntity; +import org.optaplanner.core.api.domain.lookup.PlanningId; +import org.optaplanner.core.api.domain.variable.PlanningVariable; + +/** + * adapted from optaplanner quarkus quickstart : + * https://github.com/quarkusio/quarkus-quickstarts/blob/master/optaplanner-quickstart/src/main/java/org/acme/optaplanner/domain/Lesson.java + */ +@PlanningEntity +public class Lesson { + + @PlanningId + @NotNull + private Long id; + + @NotBlank + private String subject; + @NotBlank + private String teacher; + @NotBlank + private String studentGroup; + + @PlanningVariable(valueRangeProviderRefs = "timeslotRange") + private Timeslot timeslot; + @PlanningVariable(valueRangeProviderRefs = "roomRange") + private Room room; + + private static AtomicLong increment = new AtomicLong(1); + + public Lesson() { + } + + public Lesson(String subject, String teacher, String studentGroup) { + this.id = increment.getAndIncrement(); + this.subject = subject.trim(); + this.teacher = teacher.trim(); + this.studentGroup = studentGroup.trim(); + } + + public Long getId() { + return id; + } + + public String getSubject() { + return subject; + } + + public String getTeacher() { + return teacher; + } + + public String getStudentGroup() { + return studentGroup; + } + + public Timeslot getTimeslot() { + return timeslot; + } + + public void setTimeslot(Timeslot timeslot) { + this.timeslot = timeslot; + } + + public Room getRoom() { + return room; + } + + public void setRoom(Room room) { + this.room = room; + } + + @Override + public String toString() { + return subject + "(" + id + ")"; + } + +} diff --git a/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/domain/Room.java b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/domain/Room.java new file mode 100644 index 0000000..bd93b2d --- /dev/null +++ b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/domain/Room.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.optaplanner.it.domain; + +import java.util.concurrent.atomic.AtomicLong; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import org.optaplanner.core.api.domain.lookup.PlanningId; + +/** + * adapted from optaplanner quarkus quickstart : + * https://github.com/quarkusio/quarkus-quickstarts/blob/master/optaplanner-quickstart/src/main/java/org/acme/optaplanner/domain/Room.java + */ +public class Room { + + @PlanningId + @NotNull + private Long id; + + @NotBlank + private String name; + private static AtomicLong increment = new AtomicLong(1); + + public Room() { + } + + public Room(String name) { + this.id = increment.getAndIncrement(); + this.name = name.trim(); + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } + +} diff --git a/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/domain/TimeTable.java b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/domain/TimeTable.java new file mode 100644 index 0000000..8fe3800 --- /dev/null +++ b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/domain/TimeTable.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.optaplanner.it.domain; + +import java.util.List; + +import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty; +import org.optaplanner.core.api.domain.solution.PlanningScore; +import org.optaplanner.core.api.domain.solution.PlanningSolution; +import org.optaplanner.core.api.domain.solution.drools.ProblemFactCollectionProperty; +import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider; +import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore; + +/** + * adapted from optaplanner quarkus quickstart : + * https://github.com/quarkusio/quarkus-quickstarts/blob/master/optaplanner-quickstart/src/main/java/org/acme/optaplanner/domain/Timeslot.java + */ +@PlanningSolution +public class TimeTable { + + @ProblemFactCollectionProperty + @ValueRangeProvider(id = "timeslotRange") + private List<Timeslot> timeslotList; + @ProblemFactCollectionProperty + @ValueRangeProvider(id = "roomRange") + private List<Room> roomList; + @PlanningEntityCollectionProperty + private List<Lesson> lessonList; + + @PlanningScore + private HardSoftScore score; + + public TimeTable() { + } + + public TimeTable(List<Timeslot> timeslotList, List<Room> roomList, List<Lesson> lessonList) { + this.timeslotList = timeslotList; + this.roomList = roomList; + this.lessonList = lessonList; + } + + public List<Timeslot> getTimeslotList() { + return timeslotList; + } + + public List<Room> getRoomList() { + return roomList; + } + + public List<Lesson> getLessonList() { + return lessonList; + } + + public HardSoftScore getScore() { + return score; + } + +} diff --git a/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/domain/Timeslot.java b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/domain/Timeslot.java new file mode 100644 index 0000000..57fc50f --- /dev/null +++ b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/domain/Timeslot.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.optaplanner.it.domain; + +import java.time.DayOfWeek; +import java.time.LocalTime; +import java.util.concurrent.atomic.AtomicLong; + +import javax.validation.constraints.NotNull; + +import org.optaplanner.core.api.domain.lookup.PlanningId; + +/** + * adapted from optaplanner quarkus quickstart : + * https://github.com/quarkusio/quarkus-quickstarts/blob/master/optaplanner-quickstart/src/main/java/org/acme/optaplanner/domain/TimeTable.java + */ +public class Timeslot { + + @PlanningId + @NotNull + private Long id; + + @NotNull + private DayOfWeek dayOfWeek; + @NotNull + private LocalTime startTime; + @NotNull + private LocalTime endTime; + + private static AtomicLong increment = new AtomicLong(1); + + public Timeslot() { + } + + public Timeslot(DayOfWeek dayOfWeek, LocalTime startTime, LocalTime endTime) { + this.id = increment.getAndIncrement(); + this.dayOfWeek = dayOfWeek; + this.startTime = startTime; + this.endTime = endTime; + } + + public Long getId() { + return id; + } + + public DayOfWeek getDayOfWeek() { + return dayOfWeek; + } + + public LocalTime getStartTime() { + return startTime; + } + + public LocalTime getEndTime() { + return endTime; + } + + @Override + public String toString() { + return dayOfWeek + " " + startTime; + } + +} diff --git a/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/solver/TimeTableConstraintProvider.java b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/solver/TimeTableConstraintProvider.java new file mode 100644 index 0000000..b15c6c0 --- /dev/null +++ b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/solver/TimeTableConstraintProvider.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.optaplanner.it.solver; + +import java.time.Duration; + +import org.apache.camel.quarkus.component.optaplanner.it.domain.Lesson; +import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore; +import org.optaplanner.core.api.score.stream.Constraint; +import org.optaplanner.core.api.score.stream.ConstraintFactory; +import org.optaplanner.core.api.score.stream.ConstraintProvider; +import org.optaplanner.core.api.score.stream.Joiners; + +/** + * adapted from optaplanner quarkus quickstart : + * https://github.com/quarkusio/quarkus-quickstarts/blob/master/optaplanner-quickstart/src/main/java/org/acme/optaplanner/solver/TimeTableConstraintProvider.java + */ +public class TimeTableConstraintProvider implements ConstraintProvider { + + @Override + public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + return new Constraint[] { + // Hard constraints + roomConflict(constraintFactory), + teacherConflict(constraintFactory), + studentGroupConflict(constraintFactory), + // Soft constraints + teacherRoomStability(constraintFactory), + teacherTimeEfficiency(constraintFactory), + studentGroupSubjectVariety(constraintFactory) + }; + } + + private Constraint roomConflict(ConstraintFactory constraintFactory) { + // A room can accommodate at most one lesson at the same time. + return constraintFactory + // Select each pair of 2 different lessons ... + .fromUniquePair(Lesson.class, + // ... in the same timeslot ... + Joiners.equal(Lesson::getTimeslot), + // ... in the same room ... + Joiners.equal(Lesson::getRoom)) + // ... and penalize each pair with a hard weight. + .penalize("Room conflict", HardSoftScore.ONE_HARD); + } + + private Constraint teacherConflict(ConstraintFactory constraintFactory) { + // A teacher can teach at most one lesson at the same time. + return constraintFactory + .fromUniquePair(Lesson.class, + Joiners.equal(Lesson::getTimeslot), + Joiners.equal(Lesson::getTeacher)) + .penalize("Teacher conflict", HardSoftScore.ONE_HARD); + } + + private Constraint studentGroupConflict(ConstraintFactory constraintFactory) { + // A student can attend at most one lesson at the same time. + return constraintFactory + .fromUniquePair(Lesson.class, + Joiners.equal(Lesson::getTimeslot), + Joiners.equal(Lesson::getStudentGroup)) + .penalize("Student group conflict", HardSoftScore.ONE_HARD); + } + + private Constraint teacherRoomStability(ConstraintFactory constraintFactory) { + // A teacher prefers to teach in a single room. + return constraintFactory + .fromUniquePair(Lesson.class, + Joiners.equal(Lesson::getTeacher)) + .filter((lesson1, lesson2) -> lesson1.getRoom() != lesson2.getRoom()) + .penalize("Teacher room stability", HardSoftScore.ONE_SOFT); + } + + private Constraint teacherTimeEfficiency(ConstraintFactory constraintFactory) { + // A teacher prefers to teach sequential lessons and dislikes gaps between lessons. + return constraintFactory + .from(Lesson.class) + .join(Lesson.class, Joiners.equal(Lesson::getTeacher), + Joiners.equal((lesson) -> lesson.getTimeslot().getDayOfWeek())) + .filter((lesson1, lesson2) -> { + Duration between = Duration.between(lesson1.getTimeslot().getEndTime(), + lesson2.getTimeslot().getStartTime()); + return !between.isNegative() && between.compareTo(Duration.ofMinutes(30)) <= 0; + }) + .reward("Teacher time efficiency", HardSoftScore.ONE_SOFT); + } + + private Constraint studentGroupSubjectVariety(ConstraintFactory constraintFactory) { + // A student group dislikes sequential lessons on the same subject. + return constraintFactory + .from(Lesson.class) + .join(Lesson.class, + Joiners.equal(Lesson::getSubject), + Joiners.equal(Lesson::getStudentGroup), + Joiners.equal((lesson) -> lesson.getTimeslot().getDayOfWeek())) + .filter((lesson1, lesson2) -> { + Duration between = Duration.between(lesson1.getTimeslot().getEndTime(), + lesson2.getTimeslot().getStartTime()); + return !between.isNegative() && between.compareTo(Duration.ofMinutes(30)) <= 0; + }) + .penalize("Student group subject variety", HardSoftScore.ONE_SOFT); + } + +} diff --git a/integration-tests/optaplanner/src/main/resources/application.properties b/integration-tests/optaplanner/src/main/resources/application.properties new file mode 100644 index 0000000..4156b41 --- /dev/null +++ b/integration-tests/optaplanner/src/main/resources/application.properties @@ -0,0 +1,32 @@ +## --------------------------------------------------------------------------- +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You under the Apache License, Version 2.0 +## (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## --------------------------------------------------------------------------- + +######################## +# OptaPlanner properties +# adapted from optaplanner quarkus quickstart : https://github.com/quarkusio/quarkus-quickstarts/blob/master/optaplanner-quickstart/src/main/resources/application.properties +######################## + +# The solver runs for 30 seconds. To run for 5 minutes use "5m" and for 2 hours use "2h". +quarkus.optaplanner.solver.termination.spent-limit=30s + +######################## +# Test overrides +######################## + +# Effectively disable this termination in favor of the best-score-limit +%test.quarkus.optaplanner.solver.termination.spent-limit=1h +%test.quarkus.optaplanner.solver.termination.best-score-limit=0hard/*soft diff --git a/extensions-jvm/optaplanner/integration-test/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerTest.java b/integration-tests/optaplanner/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerIT.java similarity index 69% copy from extensions-jvm/optaplanner/integration-test/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerTest.java copy to integration-tests/optaplanner/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerIT.java index ff99e1e..81cc65d 100644 --- a/extensions-jvm/optaplanner/integration-test/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerTest.java +++ b/integration-tests/optaplanner/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerIT.java @@ -16,19 +16,9 @@ */ package org.apache.camel.quarkus.component.optaplanner.it; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; +import io.quarkus.test.junit.NativeImageTest; -@QuarkusTest -class OptaplannerTest { - - @Test - public void loadComponentOptaplanner() { - /* A simple autogenerated test */ - RestAssured.get("/optaplanner/load/component/optaplanner") - .then() - .statusCode(200); - } +@NativeImageTest +class OptaplannerIT extends OptaplannerTest { } diff --git a/extensions-jvm/optaplanner/integration-test/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerTest.java b/integration-tests/optaplanner/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerTest.java similarity index 52% rename from extensions-jvm/optaplanner/integration-test/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerTest.java rename to integration-tests/optaplanner/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerTest.java index ff99e1e..de30a7e 100644 --- a/extensions-jvm/optaplanner/integration-test/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerTest.java +++ b/integration-tests/optaplanner/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerTest.java @@ -20,15 +20,38 @@ import io.quarkus.test.junit.QuarkusTest; import io.restassured.RestAssured; import org.junit.jupiter.api.Test; +import static org.hamcrest.Matchers.notNullValue; + @QuarkusTest class OptaplannerTest { @Test - public void loadComponentOptaplanner() { - /* A simple autogenerated test */ - RestAssured.get("/optaplanner/load/component/optaplanner") + public void solveSync() { + RestAssured.given() + .get("/optaplanner/solveSync") + .then() + .statusCode(200) + .body("lessonList[0].timeslot", notNullValue(null)) + .body("lessonList[0].room", notNullValue(null)); + } + + @Test + public void solveASyncWithConsumer() { + // solve async + RestAssured.given() + .get("/optaplanner/solveAsync") + .then() + .statusCode(200) + .body("lessonList[0].timeslot", notNullValue(null)) + .body("lessonList[0].room", notNullValue(null)); + + // test consumer data + RestAssured.given() + .get("/optaplanner/newBestSolution") .then() - .statusCode(200); + .statusCode(200) + .body("lessonList[0].timeslot", notNullValue(null)) + .body("lessonList[0].room", notNullValue(null)); } } diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 834e5e2..b0303c7 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -138,6 +138,7 @@ <module>olingo4</module> <module>openapi-java</module> <module>opentracing</module> + <module>optaplanner</module> <module>pdf</module> <module>pg-replication-slot</module> <module>pgevent</module> diff --git a/pom.xml b/pom.xml index 08cf44a..c9f9042 100644 --- a/pom.xml +++ b/pom.xml @@ -87,6 +87,7 @@ <okhttp.version>3.14.6</okhttp.version><!-- keep in sync with okio --> <okio.version>1.17.2</okio.version><!-- keep in sync with okhttp --> <opencensus-api.version>0.26.0</opencensus-api.version><!-- Mess in pubsub transitive deps vs google cloud deps --> + <optaplanner.version>7.46.0.Final</optaplanner.version> <quarkus.version>1.10.1.Final</quarkus.version> <quarkus-qpid-jms.version>0.21.0</quarkus-qpid-jms.version> <protobuf.version>3.11.1</protobuf.version> @@ -116,6 +117,7 @@ <istack-commons-runtime.version>3.0.10</istack-commons-runtime.version> <jakarta.mail.version>1.6.5</jakarta.mail.version> <mock-javamail.version>1.9</mock-javamail.version> + <mvel2.version>2.4.8.Final</mvel2.version> <pdfbox.version>2.0.21</pdfbox.version> <slf4j-log4j12.version>1.7.30</slf4j-log4j12.version><!-- Mess in the transitive dependencies of hbase-testing-util --> <sshd.version>2.3.0</sshd.version> diff --git a/poms/bom/pom.xml b/poms/bom/pom.xml index f12e70a..6435c1d 100644 --- a/poms/bom/pom.xml +++ b/poms/bom/pom.xml @@ -1530,6 +1530,16 @@ <groupId>org.apache.camel</groupId> <artifactId>camel-optaplanner</artifactId> <version>${camel.version}</version> + <exclusions> + <exclusion> + <groupId>org.optaplanner</groupId> + <artifactId>optaplanner-core</artifactId> + </exclusion> + <exclusion> + <groupId>org.optaplanner</groupId> + <artifactId>optaplanner-persistence-common</artifactId> + </exclusion> + </exclusions> </dependency> <dependency> <groupId>org.apache.camel</groupId> diff --git a/tooling/scripts/test-categories.yaml b/tooling/scripts/test-categories.yaml index 5327b7c..b0e8ee7 100644 --- a/tooling/scripts/test-categories.yaml +++ b/tooling/scripts/test-categories.yaml @@ -92,6 +92,7 @@ xml-json-olingo4: - weather - geocoder - lumberjack + - optaplanner dozer-social: - crypto - dozer