You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/10/28 07:41:18 UTC
[camel] 01/02: CAMEL-18614: camel-core - Updating route configuration via routes loader
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 5c6b2d3c3212757182b1b9e728ec3c1dcd2848aa
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Oct 28 09:39:50 2022 +0200
CAMEL-18614: camel-core - Updating route configuration via routes loader
---
.../apache/camel/RouteConfigurationsBuilder.java | 8 ++
.../camel/impl/engine/DefaultRoutesLoader.java | 9 ++
.../org/apache/camel/impl/DefaultCamelContext.java | 16 +++
.../java/org/apache/camel/impl/DefaultModel.java | 17 +++
.../camel/impl/lw/LightweightCamelContext.java | 10 ++
.../camel/builder/RouteConfigurationBuilder.java | 18 +++
.../main/java/org/apache/camel/model/Model.java | 16 +++
.../camel/model/RoutesConfigurationUpdateTest.java | 149 +++++++++++++++++++++
8 files changed, 243 insertions(+)
diff --git a/core/camel-api/src/main/java/org/apache/camel/RouteConfigurationsBuilder.java b/core/camel-api/src/main/java/org/apache/camel/RouteConfigurationsBuilder.java
index d9e95d599b0..b9761480791 100644
--- a/core/camel-api/src/main/java/org/apache/camel/RouteConfigurationsBuilder.java
+++ b/core/camel-api/src/main/java/org/apache/camel/RouteConfigurationsBuilder.java
@@ -29,4 +29,12 @@ public interface RouteConfigurationsBuilder {
*/
void addRouteConfigurationsToCamelContext(CamelContext context) throws Exception;
+ /**
+ * Adds or updates the route configurations from this builder to the CamelContext.
+ *
+ * @param context the Camel context
+ * @throws Exception is thrown if initialization of route configurations failed
+ */
+ void updateRouteConfigurationsToCamelContext(CamelContext context) throws Exception;
+
}
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java
index 22864c346dd..32e0c46c419 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java
@@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.camel.CamelContext;
import org.apache.camel.CamelContextAware;
import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.RouteConfigurationsBuilder;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.StaticService;
import org.apache.camel.spi.ExtendedRoutesBuilderLoader;
@@ -178,6 +179,14 @@ public class DefaultRoutesLoader extends ServiceSupport implements RoutesLoader,
Set<String> answer = new LinkedHashSet<>();
Collection<RoutesBuilder> builders = findRoutesBuilders(resources);
+ for (RoutesBuilder builder : builders) {
+ // update any existing route configurations first
+ if (builder instanceof RouteConfigurationsBuilder) {
+ RouteConfigurationsBuilder rcb = (RouteConfigurationsBuilder) builder;
+ rcb.updateRouteConfigurationsToCamelContext(getCamelContext());
+ }
+ }
+
for (RoutesBuilder builder : builders) {
// update any existing routes
Set<String> ids = builder.updateRoutesToCamelContext(getCamelContext());
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 253f1d6c322..e9c2b30bc0e 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -327,6 +327,22 @@ public class DefaultCamelContext extends SimpleCamelContext implements ModelCame
return model.getRouteConfigurationDefinitions();
}
+ @Override
+ public RouteConfigurationDefinition getRouteConfigurationDefinition(String id) {
+ if (model == null && isLightweight()) {
+ throw new IllegalStateException("Access to model not supported in lightweight mode");
+ }
+ return model.getRouteConfigurationDefinition(id);
+ }
+
+ @Override
+ public void removeRouteConfiguration(RouteConfigurationDefinition routeConfigurationDefinition) throws Exception {
+ if (model == null && isLightweight()) {
+ throw new IllegalStateException("Access to model not supported in lightweight mode");
+ }
+ model.removeRouteConfiguration(routeConfigurationDefinition);
+ }
+
@Override
public List<RouteDefinition> getRouteDefinitions() {
if (model == null && isLightweight()) {
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
index 380af8b5b8f..be04596304b 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
@@ -160,6 +160,23 @@ public class DefaultModel implements Model {
return routesConfigurations;
}
+ @Override
+ public synchronized RouteConfigurationDefinition getRouteConfigurationDefinition(String id) {
+ for (RouteConfigurationDefinition def : routesConfigurations) {
+ if (def.idOrCreate(camelContext.adapt(ExtendedCamelContext.class).getNodeIdFactory()).equals(id)) {
+ return def;
+ }
+ }
+ // you can have a global route configuration that has no ID assigned
+ return routesConfigurations.stream().filter(c -> c.getId() == null).findFirst().orElse(null);
+ }
+
+ @Override
+ public void removeRouteConfiguration(RouteConfigurationDefinition routeConfigurationDefinition) throws Exception {
+ RouteConfigurationDefinition toBeRemoved = getRouteConfigurationDefinition(routeConfigurationDefinition.getId());
+ this.routesConfigurations.remove(toBeRemoved);
+ }
+
@Override
public synchronized void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception {
if (routeDefinitions == null || routeDefinitions.isEmpty()) {
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
index 30e22f79638..53a5f2f2116 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
@@ -1875,6 +1875,16 @@ public class LightweightCamelContext implements ExtendedCamelContext, CatalogCam
return getModelCamelContext().getRouteConfigurationDefinitions();
}
+ @Override
+ public void removeRouteConfiguration(RouteConfigurationDefinition routeConfigurationDefinition) throws Exception {
+ getModelCamelContext().removeRouteConfiguration(routeConfigurationDefinition);
+ }
+
+ @Override
+ public RouteConfigurationDefinition getRouteConfigurationDefinition(String id) {
+ return getModelCamelContext().getRouteConfigurationDefinition(id);
+ }
+
@Override
public List<RouteDefinition> getRouteDefinitions() {
return getModelCamelContext().getRouteDefinitions();
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteConfigurationBuilder.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteConfigurationBuilder.java
index 9b7b43e70c6..0b22d14404f 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteConfigurationBuilder.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteConfigurationBuilder.java
@@ -16,6 +16,7 @@
*/
package org.apache.camel.builder;
+import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.camel.CamelContext;
@@ -79,6 +80,23 @@ public abstract class RouteConfigurationBuilder extends RouteBuilder implements
populateRoutesConfiguration();
}
+ @Override
+ public void updateRouteConfigurationsToCamelContext(CamelContext context) throws Exception {
+ setCamelContext(context);
+ routeConfigurationCollection.setCamelContext(context);
+ if (initializedConfiguration.compareAndSet(false, true)) {
+ configuration();
+ }
+ List<RouteConfigurationDefinition> list = getRouteConfigurationCollection().getRouteConfigurations();
+ if (!list.isEmpty()) {
+ // remove existing before updating
+ for (RouteConfigurationDefinition def : list) {
+ context.getExtension(Model.class).removeRouteConfiguration(def);
+ }
+ populateRoutesConfiguration();
+ }
+ }
+
protected void populateRoutesConfiguration() throws Exception {
CamelContext camelContext = getContext();
if (camelContext == null) {
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java b/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java
index 84d0792d95e..ae3528bd3de 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java
@@ -71,6 +71,22 @@ public interface Model {
*/
List<RouteConfigurationDefinition> getRouteConfigurationDefinitions();
+ /**
+ * Removes a route configuration from the context
+ *
+ * @param routeConfigurationDefinition route configuration to remove
+ * @throws Exception if the route configuration could not be removed for whatever reason
+ */
+ void removeRouteConfiguration(RouteConfigurationDefinition routeConfigurationDefinition) throws Exception;
+
+ /**
+ * Gets the route configuration definition with the given id
+ *
+ * @param id id of the route configuration
+ * @return the route configuration definition or <tt>null</tt> if not found
+ */
+ RouteConfigurationDefinition getRouteConfigurationDefinition(String id);
+
/**
* Returns a list of the current route definitions
*
diff --git a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationUpdateTest.java b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationUpdateTest.java
new file mode 100644
index 00000000000..d1ecbed63dc
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationUpdateTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.model;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.builder.RouteConfigurationBuilder;
+import org.junit.jupiter.api.Test;
+
+public class RoutesConfigurationUpdateTest extends ContextTestSupport {
+
+ @Override
+ public boolean isUseRouteBuilder() {
+ return false;
+ }
+
+ @Test
+ public void testRoutesConfigurationUpdate() throws Exception {
+ context.start();
+
+ RouteConfigurationBuilder rcb = new RouteConfigurationBuilder() {
+ @Override
+ public void configuration() throws Exception {
+ routeConfiguration("myConfig").onException(Exception.class).handled(true).to("mock:error");
+ }
+ };
+ rcb.addRouteConfigurationsToCamelContext(context);
+ RouteBuilder rb = new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start").routeId("start").routeConfigurationId("myConfig")
+ .throwException(new IllegalArgumentException("Foo"));
+
+ from("direct:start2").routeId("start2").routeConfigurationId("myConfig")
+ .throwException(new IllegalArgumentException("Foo2"));
+ }
+ };
+ rb.addRoutesToCamelContext(context);
+
+ getMockEndpoint("mock:error").expectedBodiesReceived("Hello World", "Bye World");
+ getMockEndpoint("mock:error2").expectedMessageCount(0);
+ template.sendBody("direct:start", "Hello World");
+ template.sendBody("direct:start2", "Bye World");
+ assertMockEndpointsSatisfied();
+
+ // update route configuration and routes (remove routes first)
+ context.getRouteController().removeAllRoutes();
+ RouteConfigurationBuilder rcb2 = new RouteConfigurationBuilder() {
+ @Override
+ public void configuration() throws Exception {
+ routeConfiguration("myConfig").onException(Exception.class).handled(true).to("mock:error2");
+ }
+ };
+ rcb2.updateRouteConfigurationsToCamelContext(context);
+ RouteBuilder rb2 = new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start").routeId("start").routeConfigurationId("myConfig")
+ .throwException(new IllegalArgumentException("Foo"));
+
+ from("direct:start2").routeId("start2").routeConfigurationId("myConfig")
+ .throwException(new IllegalArgumentException("Foo2"));
+ }
+ };
+ rb2.updateRoutesToCamelContext(context);
+
+ resetMocks();
+
+ getMockEndpoint("mock:error").expectedMessageCount(0);
+ getMockEndpoint("mock:error2").expectedBodiesReceived("Hello World2", "Bye World2");
+ template.sendBody("direct:start", "Hello World2");
+ template.sendBody("direct:start2", "Bye World2");
+ assertMockEndpointsSatisfied();
+ }
+
+ @Test
+ public void testRoutesConfigurationGlobalUpdate() throws Exception {
+ context.start();
+
+ RouteConfigurationBuilder rcb = new RouteConfigurationBuilder() {
+ @Override
+ public void configuration() throws Exception {
+ routeConfiguration().onException(Exception.class).handled(true).to("mock:error");
+ }
+ };
+ rcb.addRouteConfigurationsToCamelContext(context);
+ RouteBuilder rb = new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start").routeId("start")
+ .throwException(new IllegalArgumentException("Foo"));
+
+ from("direct:start2").routeId("start2")
+ .throwException(new IllegalArgumentException("Foo2"));
+ }
+ };
+ rb.addRoutesToCamelContext(context);
+
+ getMockEndpoint("mock:error").expectedBodiesReceived("Hello World", "Bye World");
+ getMockEndpoint("mock:error2").expectedMessageCount(0);
+ template.sendBody("direct:start", "Hello World");
+ template.sendBody("direct:start2", "Bye World");
+ assertMockEndpointsSatisfied();
+
+ // update route configuration and routes (remove routes first)
+ context.getRouteController().removeAllRoutes();
+ RouteConfigurationBuilder rcb2 = new RouteConfigurationBuilder() {
+ @Override
+ public void configuration() throws Exception {
+ routeConfiguration().onException(Exception.class).handled(true).to("mock:error2");
+ }
+ };
+ rcb2.updateRouteConfigurationsToCamelContext(context);
+ RouteBuilder rb2 = new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start").routeId("start")
+ .throwException(new IllegalArgumentException("Foo"));
+
+ from("direct:start2").routeId("start2")
+ .throwException(new IllegalArgumentException("Foo2"));
+ }
+ };
+ rb2.updateRoutesToCamelContext(context);
+
+ resetMocks();
+
+ getMockEndpoint("mock:error").expectedMessageCount(0);
+ getMockEndpoint("mock:error2").expectedBodiesReceived("Hello World2", "Bye World2");
+ template.sendBody("direct:start", "Hello World2");
+ template.sendBody("direct:start2", "Bye World2");
+ assertMockEndpointsSatisfied();
+ }
+
+}