Repository: camel
Updated Branches:
refs/heads/master 32d75e290 -> cba859770
Added consumer, producer with event listeners, async and daemon solving features
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/cba85977
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/cba85977
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/cba85977
Branch: refs/heads/master
Commit: cba859770c005dea2bb217e672adf40de682e416
Parents: 32d75e2
Author: Bilgin Ibryam <bibryam@apache.org>
Authored: Fri Aug 21 02:09:43 2015 +0100
Committer: Bilgin Ibryam <bibryam@apache.org>
Committed: Fri Aug 21 02:09:43 2015 +0100
----------------------------------------------------------------------
.../optaplanner/OptaPlannerComponent.java | 12 +-
.../optaplanner/OptaPlannerConfiguration.java | 83 +++++++++++++
.../optaplanner/OptaPlannerConstants.java | 28 +++++
.../optaplanner/OptaPlannerConsumer.java | 75 +++++++++++
.../optaplanner/OptaPlannerEndpoint.java | 80 +++++++-----
.../optaplanner/OptaPlannerProducer.java | 124 +++++++++++++++++++
.../optaplanner/OptaPlannerAsyncSolverTest.java | 63 ++++++++++
.../optaplanner/OptaPlannerConsumerTest.java | 70 +++++++++++
.../OptaPlannerDaemonSolverTest.java | 96 ++++++++++++++
.../optaplanner/OptaPlannerSyncSolverTest.java | 55 ++++++++
.../component/optaplanner/OptaPlannerTest.java | 55 --------
.../optaplanner/daemonSolverConfig.xml | 55 ++++++++
.../component/optaplanner/solverConfig.xml | 2 +-
13 files changed, 704 insertions(+), 94 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/cba85977/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerComponent.java
b/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerComponent.java
index cb59460..b188d39 100644
--- a/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerComponent.java
+++ b/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerComponent.java
@@ -20,7 +20,6 @@ import java.util.Map;
import org.apache.camel.Endpoint;
import org.apache.camel.impl.UriEndpointComponent;
-import org.optaplanner.core.api.solver.SolverFactory;
/**
* OptaPlanner component for Camel
@@ -32,13 +31,10 @@ public class OptaPlannerComponent extends UriEndpointComponent {
}
protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object>
parameters) throws Exception {
- SolverFactory solverFactory = SolverFactory.createFromXmlResource(remaining);
-
- OptaPlannerEndpoint endpoint = new OptaPlannerEndpoint(uri, this, remaining);
- endpoint.setSolverFactory(solverFactory);
- setProperties(endpoint, parameters);
-
- return endpoint;
+ OptaPlannerConfiguration configuration = new OptaPlannerConfiguration();
+ configuration.setConfigFile(remaining);
+ setProperties(configuration, parameters);
+ return new OptaPlannerEndpoint(uri, this, configuration);
}
}
http://git-wip-us.apache.org/repos/asf/camel/blob/cba85977/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerConfiguration.java
b/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerConfiguration.java
new file mode 100644
index 0000000..0e70c77
--- /dev/null
+++ b/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerConfiguration.java
@@ -0,0 +1,83 @@
+/**
+ * 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.component.optaplanner;
+
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriParams;
+import org.apache.camel.spi.UriPath;
+
+@UriParams
+public class OptaPlannerConfiguration {
+
+ /**
+ * Specifies the solverId to user for the solver instance key
+ */
+ @UriParam(label = "common", defaultValue = "DEFAULT_SOLVER")
+ private String solverId = OptaPlannerConstants.DEFAULT_SOLVER_ID;
+
+ /**
+ * Specifies the location to the solver file
+ */
+ @UriPath
+ @Metadata(required = "true")
+ private String configFile;
+
+ /**
+ * Specifies the thread pool size to use when async is true
+ */
+ @UriParam(label = "producer", defaultValue = "10")
+ private int threadPoolSize = 10;
+
+ /**
+ * Specifies to perform operations in async mode
+ */
+ @UriParam(label = "producer", defaultValue = "false")
+ private boolean async;
+
+ public String getSolverId() {
+ return solverId;
+ }
+
+ public void setSolverId(String solverId) {
+ this.solverId = solverId;
+ }
+
+ public void setConfigFile(String configFile) {
+ this.configFile = configFile;
+ }
+
+ public String getConfigFile() {
+ return configFile;
+ }
+
+ public int getThreadPoolSize() {
+ return threadPoolSize;
+ }
+
+ public void setThreadPoolSize(int threadPoolSize) {
+ this.threadPoolSize = threadPoolSize;
+ }
+
+ public boolean isAsync() {
+ return async;
+ }
+
+ public void setAsync(boolean async) {
+ this.async = async;
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/cba85977/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerConstants.java
----------------------------------------------------------------------
diff --git a/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerConstants.java
b/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerConstants.java
new file mode 100644
index 0000000..986a161
--- /dev/null
+++ b/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerConstants.java
@@ -0,0 +1,28 @@
+/**
+ * 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.component.optaplanner;
+
+public interface OptaPlannerConstants {
+ String DEFAULT_SOLVER_ID = "DEFAULT_SOLVER";
+ String SOLVER_ID = "CamelOptaPlannerSolverId";
+ String IS_ASYNC = "CamelOptaPlannerIsAsync";
+ String BEST_SOLUTION = "CamelOptaPlannerBestSolution";
+ String TIME_SPENT = "CamelOptaPlannerTimeSpent";
+ String IS_SOLVING = "CamelOptaPlannerIsSolving";
+ String IS_TERMINATE_EARLY = "CamelOptaPlannerIsTerminateEarly";
+ String IS_FACT_PROCESSED = "CamelOptaPlannerIsFactProcessed";
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/cba85977/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerConsumer.java
----------------------------------------------------------------------
diff --git a/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerConsumer.java
b/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerConsumer.java
new file mode 100644
index 0000000..0e10a79
--- /dev/null
+++ b/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerConsumer.java
@@ -0,0 +1,75 @@
+/**
+ * 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.component.optaplanner;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.impl.DefaultConsumer;
+import org.optaplanner.core.api.solver.Solver;
+import org.optaplanner.core.api.solver.event.BestSolutionChangedEvent;
+import org.optaplanner.core.api.solver.event.SolverEventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * OptaPlanner component for Camel
+ */
+public class OptaPlannerConsumer extends DefaultConsumer {
+ private static final transient Logger LOGGER = LoggerFactory.getLogger(OptaPlannerConsumer.class);
+ private final OptaPlannerEndpoint endpoint;
+ private final OptaPlannerConfiguration configuration;
+ private final SolverEventListener listener;
+
+ public OptaPlannerConsumer(OptaPlannerEndpoint endpoint, Processor processor, OptaPlannerConfiguration
configuration) {
+ super(endpoint, processor);
+ this.endpoint = endpoint;
+ this.configuration = configuration;
+ listener = new SolverEventListener() {
+ @Override
+ public void bestSolutionChanged(BestSolutionChangedEvent event) {
+ if (event.isEveryProblemFactChangeProcessed() && event.isNewBestSolutionInitialized())
{
+ processEvent(event);
+ }
+ }
+ };
+ }
+
+ public void processEvent(BestSolutionChangedEvent event) {
+ Exchange exchange = getEndpoint().createExchange();
+ exchange.getOut().setHeader(OptaPlannerConstants.BEST_SOLUTION, event.getNewBestSolution());
+ try {
+ getProcessor().process(exchange);
+ } catch (Exception e) {
+ LOGGER.error("Error processing event ", e);
+ }
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ Solver solver = endpoint.getOrCreateSolver(configuration.getSolverId());
+ solver.addEventListener(listener);
+ super.doStart();
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ Solver solver = endpoint.getOrCreateSolver(configuration.getSolverId());
+ solver.removeEventListener(listener);
+ super.doStop();
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/camel/blob/cba85977/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerEndpoint.java
b/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerEndpoint.java
index 3eade1b..8424530 100644
--- a/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerEndpoint.java
+++ b/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerEndpoint.java
@@ -16,63 +16,83 @@
*/
package org.apache.camel.component.optaplanner;
+import java.util.HashMap;
+import java.util.Map;
+
import org.apache.camel.Component;
-import org.apache.camel.Exchange;
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.component.ResourceEndpoint;
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.impl.DefaultEndpoint;
import org.apache.camel.spi.UriEndpoint;
-import org.apache.camel.util.ObjectHelper;
-import org.optaplanner.core.api.domain.solution.Solution;
+import org.apache.camel.spi.UriParam;
import org.optaplanner.core.api.solver.Solver;
import org.optaplanner.core.api.solver.SolverFactory;
/**
* OptaPlanner endpoint for Camel
*/
-@UriEndpoint(scheme = "optaplanner", title = "OptaPlanner", syntax = "optaplanner:resourceUri",
producerOnly = true, label = "engine,planning")
-public class OptaPlannerEndpoint extends ResourceEndpoint {
+@UriEndpoint(scheme = "optaplanner", title = "OptaPlanner", syntax = "optaplanner:resourceUri",
label = "engine,planning")
+public class OptaPlannerEndpoint extends DefaultEndpoint {
+ protected static final Map<String, Solver> SOLVERS = new HashMap<String, Solver>();
+ @UriParam
+ private OptaPlannerConfiguration configuration;
private SolverFactory solverFactory;
public OptaPlannerEndpoint() {
}
- public OptaPlannerEndpoint(String uri, Component component, String resourceUri) {
- super(uri, component, resourceUri);
+ public OptaPlannerEndpoint(String uri, Component component, OptaPlannerConfiguration
configuration) {
+ super(uri, component);
+ this.configuration = configuration;
+ solverFactory = SolverFactory.createFromXmlResource(configuration.getConfigFile());
}
- public SolverFactory getSolverFactory() {
- return solverFactory;
+ protected Solver getOrCreateSolver(String solverId) throws Exception {
+ synchronized (SOLVERS) {
+ Solver solver = SOLVERS.get(solverId);
+ if (solver == null) {
+ solver = createSolver();
+ SOLVERS.put(solverId, solver);
+ }
+ return solver;
+ }
}
- public void setSolverFactory(SolverFactory solverFactory) {
- this.solverFactory = solverFactory;
+ protected Solver createSolver() {
+ return solverFactory.buildSolver();
}
- @Override
- public ExchangePattern getExchangePattern() {
- return ExchangePattern.InOut;
+ protected Solver getSolver(String solverId) {
+ synchronized (SOLVERS) {
+ return SOLVERS.get(solverId);
+ }
}
@Override
- protected String createEndpointUri() {
- return "optaplanner:" + getResourceUri();
+ public Producer createProducer() throws Exception {
+ return new OptaPlannerProducer(this, configuration);
}
@Override
- protected void onExchange(Exchange exchange) throws Exception {
- ObjectHelper.notNull(solverFactory, "solverFactory");
- Solver solver = solverFactory.buildSolver();
-
- Solution planningProblem = exchange.getIn().getMandatoryBody(Solution.class);
-
- solver.solve(planningProblem);
- Solution bestSolution = solver.getBestSolution();
+ public Consumer createConsumer(Processor processor) throws Exception {
+ return new OptaPlannerConsumer(this, processor, configuration);
+ }
- exchange.getOut().setBody(bestSolution);
- // propagate headers and attachments
- exchange.getOut().setHeaders(exchange.getIn().getHeaders());
- exchange.getOut().setAttachments(exchange.getIn().getAttachments());
+ @Override
+ public boolean isSingleton() {
+ return true;
}
+ @Override
+ protected void doStop() throws Exception {
+ synchronized (SOLVERS) {
+ for (Solver solver : SOLVERS.values()) {
+ solver.terminateEarly();
+ SOLVERS.remove(solver);
+ }
+ }
+ super.doStop();
+ }
}
http://git-wip-us.apache.org/repos/asf/camel/blob/cba85977/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerProducer.java
b/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerProducer.java
new file mode 100644
index 0000000..c862cd7
--- /dev/null
+++ b/components/camel-optaplanner/src/main/java/org/apache/camel/component/optaplanner/OptaPlannerProducer.java
@@ -0,0 +1,124 @@
+/**
+ * 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.component.optaplanner;
+
+import java.util.concurrent.ExecutorService;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.impl.DefaultProducer;
+import org.optaplanner.core.api.domain.solution.Solution;
+import org.optaplanner.core.api.solver.Solver;
+import org.optaplanner.core.impl.solver.ProblemFactChange;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OptaPlannerProducer extends DefaultProducer {
+ private static final transient Logger LOGGER = LoggerFactory.getLogger(OptaPlannerProducer.class);
+ private ExecutorService executor;
+ private final OptaPlannerEndpoint endpoint;
+ private final OptaPlannerConfiguration configuration;
+
+ public OptaPlannerProducer(OptaPlannerEndpoint endpoint, OptaPlannerConfiguration configuration)
{
+ super(endpoint);
+ this.endpoint = endpoint;
+ this.configuration = configuration;
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ if (configuration.isAsync()) {
+ executor = endpoint.getCamelContext().getExecutorServiceManager().newFixedThreadPool(
+ this, endpoint.getEndpointUri(), configuration.getThreadPoolSize());
+ }
+ super.doStart();
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ if (executor != null) {
+ endpoint.getCamelContext().getExecutorServiceManager().shutdown(executor);
+ executor = null;
+ }
+ super.doStop();
+ }
+
+ @Override
+ public synchronized void process(Exchange exchange) throws Exception {
+ final Object body = exchange.getIn().getMandatoryBody();
+ final String solverId = getSolverId(exchange);
+
+ if (body instanceof Solution) {
+ if (isAsync(exchange)) {
+ LOGGER.debug("Asynchronously solving problem: [{}] with id [{}]", body, solverId);
+ final Solver solver = endpoint.getOrCreateSolver(solverId);
+ executor.submit(new Runnable() {
+ @Override
+ public void run() {
+ solver.solve((Solution)body);
+ }
+ });
+ } else {
+ LOGGER.debug("Synchronously solving problem: [{}] with id [{}]", body, solverId);
+ Solver solver = endpoint.getSolver(solverId);
+ if (solver == null) {
+ solver = endpoint.createSolver();
+ }
+ solver.solve((Solution) body);
+ populateResult(exchange, solver);
+ }
+ } else if (body instanceof ProblemFactChange) {
+ LOGGER.debug("Adding ProblemFactChange to solver: [{}] with id [{}]", body, solverId);
+ Solver solver = endpoint.getOrCreateSolver(solverId);
+ solver.addProblemFactChange((ProblemFactChange)body);
+ if (!isAsync(exchange)) {
+ while (!solver.isEveryProblemFactChangeProcessed()) {
+ Thread.currentThread().sleep(100);
+ }
+ }
+ populateResult(exchange, solver);
+ } else {
+ LOGGER.debug("Retrieving best score for solver: [{}]", solverId);
+ Solver solver = endpoint.getSolver(solverId);
+ if (solver == null) {
+ throw new RuntimeException("Solver not found: " + solverId);
+ }
+ populateResult(exchange, solver);
+ }
+ }
+
+ private void populateResult(Exchange exchange, Solver solver) {
+ exchange.getIn().setBody(solver.getBestSolution());
+ exchange.getIn().setHeader(OptaPlannerConstants.TIME_SPENT, solver.getTimeMillisSpent());
+ exchange.getIn().setHeader(OptaPlannerConstants.IS_FACT_PROCESSED, solver.isEveryProblemFactChangeProcessed());
+ exchange.getIn().setHeader(OptaPlannerConstants.IS_TERMINATE_EARLY, solver.isTerminateEarly());
+ exchange.getIn().setHeader(OptaPlannerConstants.IS_SOLVING, solver.isSolving());
+ }
+
+ private String getSolverId(Exchange exchange) throws Exception {
+ String solverId = exchange.getIn().getHeader(OptaPlannerConstants.SOLVER_ID, String.class);
+ if (solverId == null) {
+ solverId = configuration.getSolverId();
+ }
+ LOGGER.debug("SolverId: [{}]", solverId);
+ return solverId;
+ }
+
+ private boolean isAsync(Exchange exchange) {
+ Boolean isAsync = exchange.getIn().getHeader(OptaPlannerConstants.IS_ASYNC, Boolean.class);
+ return isAsync != null ? isAsync : configuration.isAsync();
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/cba85977/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerAsyncSolverTest.java
----------------------------------------------------------------------
diff --git a/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerAsyncSolverTest.java
b/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerAsyncSolverTest.java
new file mode 100644
index 0000000..cdbafe7
--- /dev/null
+++ b/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerAsyncSolverTest.java
@@ -0,0 +1,63 @@
+/**
+ * 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.component.optaplanner;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+import org.optaplanner.examples.cloudbalancing.domain.CloudBalance;
+import org.optaplanner.examples.cloudbalancing.persistence.CloudBalancingGenerator;
+
+/**
+ * OptaPlanner unit test with Camel
+ */
+public class OptaPlannerAsyncSolverTest extends CamelTestSupport {
+
+ @Test
+ public void testAsynchronousProblemSolving() throws Exception {
+ getMockEndpoint("mock:result").setExpectedCount(1);
+ CloudBalancingGenerator generator = new CloudBalancingGenerator(true);
+ final CloudBalance planningProblem = generator.createCloudBalance(4, 12);
+ assertNull(planningProblem.getScore());
+ assertNull(planningProblem.getProcessList().get(0).getComputer());
+
+ template.requestBody("direct:in", planningProblem);
+ getMockEndpoint("mock:result").assertIsSatisfied();
+
+ CloudBalance bestSolution = (CloudBalance) template.requestBody("direct:in", "foo");
+
+ assertEquals(4, bestSolution.getComputerList().size());
+ assertEquals(12, bestSolution.getProcessList().size());
+ assertNotNull(bestSolution.getScore());
+ assertTrue(bestSolution.getScore().isFeasible());
+ assertNotNull(bestSolution.getProcessList().get(0).getComputer());
+ }
+
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ public void configure() {
+ from("direct:in").
+ to("optaplanner:org/apache/camel/component/optaplanner/solverConfig.xml?async=true");
+
+ from("optaplanner:org/apache/camel/component/optaplanner/solverConfig.xml").
+ to("log:com.mycompany.order?showAll=true&multiline=true").
+ to("mock:result");
+ }
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/cba85977/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerConsumerTest.java
----------------------------------------------------------------------
diff --git a/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerConsumerTest.java
b/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerConsumerTest.java
new file mode 100644
index 0000000..2e86201
--- /dev/null
+++ b/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerConsumerTest.java
@@ -0,0 +1,70 @@
+/**
+ * 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.component.optaplanner;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.commons.lang.ObjectUtils;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.optaplanner.core.impl.score.director.ScoreDirector;
+import org.optaplanner.core.impl.solver.ProblemFactChange;
+import org.optaplanner.examples.cloudbalancing.domain.CloudBalance;
+import org.optaplanner.examples.cloudbalancing.domain.CloudComputer;
+import org.optaplanner.examples.cloudbalancing.domain.CloudProcess;
+import org.optaplanner.examples.cloudbalancing.persistence.CloudBalancingGenerator;
+
+/**
+ * OptaPlanner unit test with Camel
+ */
+public class OptaPlannerConsumerTest extends CamelTestSupport {
+
+ @Test
+ public void testSynchronousProblemSolving() throws Exception {
+ CloudBalancingGenerator generator = new CloudBalancingGenerator(true);
+ final CloudBalance planningProblem = generator.createCloudBalance(4, 12);
+ assertNull(planningProblem.getScore());
+ assertNull(planningProblem.getProcessList().get(0).getComputer());
+
+ CloudBalance bestSolution = (CloudBalance) template.requestBody("direct:in", planningProblem);
+
+ assertEquals(4, bestSolution.getComputerList().size());
+ assertEquals(12, bestSolution.getProcessList().size());
+ assertNotNull(bestSolution.getScore());
+ assertTrue(bestSolution.getScore().isFeasible());
+ assertNotNull(bestSolution.getProcessList().get(0).getComputer());
+ }
+
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ public void configure() {
+ from("direct:in").
+ to("optaplanner:org/apache/camel/component/optaplanner/solverConfig.xml");
+
+ from("optaplanner:org/apache/camel/component/optaplanner/solverConfig.xml").
+ to("log:com.mycompany.order?showAll=true&multiline=true").
+ to("mock:result");
+ }
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/cba85977/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerDaemonSolverTest.java
----------------------------------------------------------------------
diff --git a/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerDaemonSolverTest.java
b/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerDaemonSolverTest.java
new file mode 100644
index 0000000..596fd16
--- /dev/null
+++ b/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerDaemonSolverTest.java
@@ -0,0 +1,96 @@
+/**
+ * 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.component.optaplanner;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.commons.lang.ObjectUtils;
+import org.junit.Test;
+import org.optaplanner.core.impl.score.director.ScoreDirector;
+import org.optaplanner.core.impl.solver.ProblemFactChange;
+import org.optaplanner.examples.cloudbalancing.domain.CloudBalance;
+import org.optaplanner.examples.cloudbalancing.domain.CloudComputer;
+import org.optaplanner.examples.cloudbalancing.domain.CloudProcess;
+import org.optaplanner.examples.cloudbalancing.persistence.CloudBalancingGenerator;
+
+/**
+ * OptaPlanner unit test with Camel
+ */
+public class OptaPlannerDaemonSolverTest extends CamelTestSupport {
+
+ @Test
+ public void testAsynchronousProblemSolving() throws Exception {
+ getMockEndpoint("mock:result").setExpectedCount(1);
+ CloudBalancingGenerator generator = new CloudBalancingGenerator(true);
+ final CloudBalance planningProblem = generator.createCloudBalance(4, 12);
+ assertNull(planningProblem.getScore());
+ assertNull(planningProblem.getProcessList().get(0).getComputer());
+
+ template.requestBody("direct:in", planningProblem);
+ getMockEndpoint("mock:result").assertIsSatisfied();
+ getMockEndpoint("mock:result").reset();
+ getMockEndpoint("mock:result").setExpectedCount(1);
+
+ template.requestBody("direct:in", new ProblemFactChange() {
+ @Override
+ public void doChange(ScoreDirector scoreDirector) {
+ CloudBalance cloudBalance = (CloudBalance) scoreDirector.getWorkingSolution();
+ CloudComputer computer = null;
+ for (CloudProcess process : cloudBalance.getProcessList()) {
+ computer = process.getComputer();
+ if (ObjectUtils.equals(process.getComputer(), computer)) {
+ scoreDirector.beforeVariableChanged(process, "computer");
+ process.setComputer(null);
+ scoreDirector.afterVariableChanged(process, "computer");
+ }
+ }
+ cloudBalance.setComputerList(new ArrayList<CloudComputer>(cloudBalance.getComputerList()));
+ for (Iterator<CloudComputer> it = cloudBalance.getComputerList().iterator();
it.hasNext();) {
+ CloudComputer workingComputer = it.next();
+ if (ObjectUtils.equals(workingComputer, computer)) {
+ scoreDirector.beforeProblemFactRemoved(workingComputer);
+ it.remove(); // remove from list
+ scoreDirector.beforeProblemFactRemoved(workingComputer);
+ break;
+ }
+ }
+ }
+ });
+
+ getMockEndpoint("mock:result").assertIsSatisfied();
+ CloudBalance bestSolution = (CloudBalance) template.requestBody("direct:in", "foo");
+
+ assertEquals(3, bestSolution.getComputerList().size());
+ }
+
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ public void configure() {
+ from("direct:in").
+ to("optaplanner:org/apache/camel/component/optaplanner/daemonSolverConfig.xml?async=true");
+
+ from("optaplanner:org/apache/camel/component/optaplanner/daemonSolverConfig.xml").
+ to("log:com.mycompany.order?showAll=true&multiline=true").
+ to("mock:result");
+ }
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/cba85977/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerSyncSolverTest.java
----------------------------------------------------------------------
diff --git a/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerSyncSolverTest.java
b/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerSyncSolverTest.java
new file mode 100644
index 0000000..ed2e7c6
--- /dev/null
+++ b/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerSyncSolverTest.java
@@ -0,0 +1,55 @@
+/**
+ * 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.component.optaplanner;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+import org.optaplanner.examples.cloudbalancing.domain.CloudBalance;
+import org.optaplanner.examples.cloudbalancing.persistence.CloudBalancingGenerator;
+
+/**
+ * OptaPlanner unit test with Camel
+ */
+public class OptaPlannerSyncSolverTest extends CamelTestSupport {
+
+ @Test
+ public void testSynchronousProblemSolving() throws Exception {
+ CloudBalancingGenerator generator = new CloudBalancingGenerator(true);
+ final CloudBalance planningProblem = generator.createCloudBalance(4, 12);
+ assertNull(planningProblem.getScore());
+ assertNull(planningProblem.getProcessList().get(0).getComputer());
+
+ CloudBalance bestSolution = (CloudBalance) template.requestBody("direct:in", planningProblem);
+
+ assertEquals(4, bestSolution.getComputerList().size());
+ assertEquals(12, bestSolution.getProcessList().size());
+ assertNotNull(bestSolution.getScore());
+ assertTrue(bestSolution.getScore().isFeasible());
+ assertNotNull(bestSolution.getProcessList().get(0).getComputer());
+ }
+
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ public void configure() {
+ from("direct:in").
+ to("optaplanner:org/apache/camel/component/optaplanner/solverConfig.xml");
+ }
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/cba85977/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerTest.java
----------------------------------------------------------------------
diff --git a/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerTest.java
b/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerTest.java
deleted file mode 100644
index 5a7fd15..0000000
--- a/components/camel-optaplanner/src/test/java/org/apache/camel/component/optaplanner/OptaPlannerTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * 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.component.optaplanner;
-
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.test.junit4.CamelTestSupport;
-import org.junit.Test;
-import org.optaplanner.examples.cloudbalancing.domain.CloudBalance;
-import org.optaplanner.examples.cloudbalancing.persistence.CloudBalancingGenerator;
-
-/**
- * OptaPlanner unit test with Camel
- */
-public class OptaPlannerTest extends CamelTestSupport {
-
- @Test
- public void testCloudBalance4computers12processes() throws Exception {
- CloudBalancingGenerator generator = new CloudBalancingGenerator(true);
- final CloudBalance planningProblem = generator.createCloudBalance(4, 12);
- assertNull(planningProblem.getScore());
- assertNull(planningProblem.getProcessList().get(0).getComputer());
-
- CloudBalance bestSolution = (CloudBalance) template.requestBody("direct:in", planningProblem);
-
- assertEquals(4, bestSolution.getComputerList().size());
- assertEquals(12, bestSolution.getProcessList().size());
- assertNotNull(bestSolution.getScore());
- assertTrue(bestSolution.getScore().isFeasible());
- assertNotNull(bestSolution.getProcessList().get(0).getComputer());
- }
-
- protected RouteBuilder createRouteBuilder() {
- return new RouteBuilder() {
- public void configure() {
- from("direct:in").
- to("optaplanner:org/apache/camel/component/optaplanner/solverConfig.xml");
- }
- };
- }
-
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/cba85977/components/camel-optaplanner/src/test/resources/org/apache/camel/component/optaplanner/daemonSolverConfig.xml
----------------------------------------------------------------------
diff --git a/components/camel-optaplanner/src/test/resources/org/apache/camel/component/optaplanner/daemonSolverConfig.xml
b/components/camel-optaplanner/src/test/resources/org/apache/camel/component/optaplanner/daemonSolverConfig.xml
new file mode 100644
index 0000000..45e60f3
--- /dev/null
+++ b/components/camel-optaplanner/src/test/resources/org/apache/camel/component/optaplanner/daemonSolverConfig.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<solver>
+
+ <!-- Run in daemon mode -->
+ <daemon>true</daemon>
+
+ <!--<environmentMode>FAST_ASSERT</environmentMode>-->
+
+ <!-- Domain model configuration -->
+ <solutionClass>org.optaplanner.examples.cloudbalancing.domain.CloudBalance</solutionClass>
+ <entityClass>org.optaplanner.examples.cloudbalancing.domain.CloudProcess</entityClass>
+
+ <!-- Score configuration -->
+ <scoreDirectorFactory>
+ <scoreDefinitionType>HARD_SOFT</scoreDefinitionType>
+ <scoreDrl>org/optaplanner/examples/cloudbalancing/solver/cloudBalancingScoreRules.drl</scoreDrl>
+ </scoreDirectorFactory>
+
+ <!-- Optimization algorithms configuration -->
+ <termination>
+ <terminationCompositionStyle>AND</terminationCompositionStyle>
+ <secondsSpentLimit>2</secondsSpentLimit>
+ <bestScoreFeasible>true</bestScoreFeasible>
+ </termination>
+ <constructionHeuristic>
+ <constructionHeuristicType>FIRST_FIT_DECREASING</constructionHeuristicType>
+ <forager>
+ <pickEarlyType>FIRST_NON_DETERIORATING_SCORE</pickEarlyType>
+ </forager>
+ </constructionHeuristic>
+ <localSearch>
+ <acceptor>
+ <entityTabuSize>7</entityTabuSize>
+ </acceptor>
+ <forager>
+ <acceptedCountLimit>1000</acceptedCountLimit>
+ </forager>
+ </localSearch>
+</solver>
http://git-wip-us.apache.org/repos/asf/camel/blob/cba85977/components/camel-optaplanner/src/test/resources/org/apache/camel/component/optaplanner/solverConfig.xml
----------------------------------------------------------------------
diff --git a/components/camel-optaplanner/src/test/resources/org/apache/camel/component/optaplanner/solverConfig.xml
b/components/camel-optaplanner/src/test/resources/org/apache/camel/component/optaplanner/solverConfig.xml
index 6ecf1a6..68f3e5b 100644
--- a/components/camel-optaplanner/src/test/resources/org/apache/camel/component/optaplanner/solverConfig.xml
+++ b/components/camel-optaplanner/src/test/resources/org/apache/camel/component/optaplanner/solverConfig.xml
@@ -31,7 +31,7 @@
<!-- Optimization algorithms configuration -->
<termination>
<terminationCompositionStyle>AND</terminationCompositionStyle>
- <secondsSpentLimit>10</secondsSpentLimit>
+ <secondsSpentLimit>2</secondsSpentLimit>
<bestScoreFeasible>true</bestScoreFeasible>
</termination>
<constructionHeuristic>
|