This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch camel-3.x in repository https://gitbox.apache.org/repos/asf/camel.git
commit 2277b60789080c0cc4278c162098e741d966f35a Author: Claus Ibsen <[email protected]> AuthorDate: Sat Feb 18 11:08:41 2023 +0100 CAMEL-19071: camel-main / camel-jbang - Reload properties should reload components in dev mode. --- .../{ResourceReload.java => PropertiesReload.java} | 15 +++-- .../java/org/apache/camel/spi/ResourceReload.java | 7 +- .../org/apache/camel/main/BaseMainSupport.java | 75 ++++++++++++++++++++++ .../apache/camel/main/MainPropertiesReload.java | 57 ++++++++++++++++ .../camel/support/RouteWatcherReloadStrategy.java | 20 +++++- 5 files changed, 163 insertions(+), 11 deletions(-) diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/ResourceReload.java b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesReload.java similarity index 65% copy from core/camel-api/src/main/java/org/apache/camel/spi/ResourceReload.java copy to core/camel-api/src/main/java/org/apache/camel/spi/PropertiesReload.java index cdbb63255e1..2c795a6cbb0 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/ResourceReload.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesReload.java @@ -16,18 +16,21 @@ */ package org.apache.camel.spi; +import java.util.Properties; + /** - * Listener for re-loading a {@link Resource} such as a Camel route. + * Listener for re-loading a {@link java.util.Properties} such as a Camel route. */ @FunctionalInterface -public interface ResourceReload { +public interface PropertiesReload { /** - * Callback when the resource is re-loaded. + * Callback when the properties is re-loaded. * - * @param name name of the resource such as the file name (absolute) - * @param resource the resource + * @param name name of the resource such as the file name (absolute) + * @param properties the properties that was re-loaded + * @throws Exception error reloading properties */ - void onReload(String name, Resource resource); + void onReload(String name, Properties properties) throws Exception; } diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/ResourceReload.java b/core/camel-api/src/main/java/org/apache/camel/spi/ResourceReload.java index cdbb63255e1..5176ef8cbcd 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/ResourceReload.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/ResourceReload.java @@ -25,9 +25,10 @@ public interface ResourceReload { /** * Callback when the resource is re-loaded. * - * @param name name of the resource such as the file name (absolute) - * @param resource the resource + * @param name name of the resource such as the file name (absolute) + * @param resource the resource + * @throws Exception error reloading the resources */ - void onReload(String name, Resource resource); + void onReload(String name, Resource resource) throws Exception; } diff --git a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java index eb4b3f90bbf..ce1b2aaa190 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java @@ -488,6 +488,8 @@ public abstract class BaseMainSupport extends BaseService { if (mainConfigurationProperties.isAutoConfigurationEnabled()) { autoConfigurationFromProperties(camelContext, autoConfiguredProperties); autowireWildcardProperties(camelContext); + // register properties reloader so we can auto-update if updated + camelContext.addService(new MainPropertiesReload(this)); } // log summary of configurations @@ -1622,8 +1624,78 @@ public abstract class BaseMainSupport extends BaseService { prop.remove(key); } + doAutoConfigurationFromProperties(camelContext, prop, properties, false, autoConfiguredProperties); + } + + protected void autoConfigurationFromReloadedProperties( + CamelContext camelContext, OrderedLocationProperties reloadedProperties) + throws Exception { + + Map<PropertyOptionKey, OrderedLocationProperties> properties = new LinkedHashMap<>(); + + // filter out wildcard properties + for (String key : reloadedProperties.stringPropertyNames()) { + if (key.contains("*")) { + String loc = reloadedProperties.getLocation(key); + wildcardProperties.put(loc, key, reloadedProperties.getProperty(key)); + } + } + // and remove wildcards + for (String key : wildcardProperties.stringPropertyNames()) { + reloadedProperties.remove(key); + } + + OrderedLocationProperties autoConfiguredProperties = new OrderedLocationProperties(); + doAutoConfigurationFromProperties(camelContext, reloadedProperties, properties, true, autoConfiguredProperties); + + // log summary of configurations + if (mainConfigurationProperties.isAutoConfigurationLogSummary() && !autoConfiguredProperties.isEmpty()) { + boolean header = false; + for (var entry : autoConfiguredProperties.entrySet()) { + String k = entry.getKey().toString(); + Object v = entry.getValue(); + String loc = locationSummary(autoConfiguredProperties, k); + + // tone down logging noise for our own internal configurations + boolean debug = loc.contains("[camel-main]"); + if (debug && !LOG.isDebugEnabled()) { + continue; + } + + if (!header) { + LOG.info("Auto-configuration summary"); + header = true; + } + + if (SensitiveUtils.containsSensitive(k)) { + if (debug) { + LOG.debug(" {} {}=xxxxxx", loc, k); + } else { + LOG.info(" {} {}=xxxxxx", loc, k); + } + } else { + if (debug) { + LOG.debug(" {} {}={}", loc, k, v); + } else { + LOG.info(" {} {}={}", loc, k, v); + } + } + } + } + } + + protected void doAutoConfigurationFromProperties( + CamelContext camelContext, OrderedLocationProperties prop, + Map<PropertyOptionKey, OrderedLocationProperties> properties, boolean reload, + OrderedLocationProperties autoConfiguredProperties) + throws Exception { + for (String key : prop.stringPropertyNames()) { computeProperties("camel.component.", key, prop, properties, name -> { + if (reload) { + // force re-creating component on reload + camelContext.removeComponent(name); + } // its an existing component name Component target = camelContext.getComponent(name); if (target == null) { @@ -1706,6 +1778,9 @@ public abstract class BaseMainSupport extends BaseService { doAutowireWildcardProperties(name, component); } }); + + // clear in case we reload later + wildcardProperties.clear(); } protected void doAutowireWildcardProperties(String name, Component component) { diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainPropertiesReload.java b/core/camel-main/src/main/java/org/apache/camel/main/MainPropertiesReload.java new file mode 100644 index 00000000000..34ddef39139 --- /dev/null +++ b/core/camel-main/src/main/java/org/apache/camel/main/MainPropertiesReload.java @@ -0,0 +1,57 @@ +/* + * 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.main; + +import java.util.Properties; + +import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; +import org.apache.camel.spi.PropertiesReload; +import org.apache.camel.support.service.ServiceSupport; +import org.apache.camel.util.OrderedLocationProperties; + +/** + * Reloading of application.properties when using Camel Main in reload mode, such as when using camel-jbang. + */ +public class MainPropertiesReload extends ServiceSupport implements PropertiesReload, CamelContextAware { + + private final BaseMainSupport main; + private CamelContext camelContext; + + public MainPropertiesReload(BaseMainSupport main) { + this.main = main; + } + + @Override + public CamelContext getCamelContext() { + return camelContext; + } + + @Override + public void setCamelContext(CamelContext camelContext) { + this.camelContext = camelContext; + } + + @Override + public void onReload(String name, Properties properties) throws Exception { + if (properties instanceof OrderedLocationProperties) { + OrderedLocationProperties prop = (OrderedLocationProperties) properties; + main.autoConfigurationFromReloadedProperties(camelContext, prop); + main.autowireWildcardProperties(camelContext); + } + } +} diff --git a/core/camel-support/src/main/java/org/apache/camel/support/RouteWatcherReloadStrategy.java b/core/camel-support/src/main/java/org/apache/camel/support/RouteWatcherReloadStrategy.java index faa64ed8997..caef6d0e41d 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/RouteWatcherReloadStrategy.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/RouteWatcherReloadStrategy.java @@ -17,6 +17,7 @@ package org.apache.camel.support; import java.io.File; +import java.io.InputStream; import java.net.URI; import java.nio.file.Files; import java.nio.file.Paths; @@ -32,10 +33,14 @@ import org.apache.camel.RuntimeCamelException; import org.apache.camel.ServiceStatus; import org.apache.camel.StartupSummaryLevel; import org.apache.camel.spi.PropertiesComponent; +import org.apache.camel.spi.PropertiesReload; import org.apache.camel.spi.Resource; import org.apache.camel.util.AntPathMatcher; import org.apache.camel.util.FileUtil; +import org.apache.camel.util.IOHelper; import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.OrderedLocationProperties; +import org.apache.camel.util.OrderedProperties; import org.apache.camel.util.URISupport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -157,13 +162,24 @@ public class RouteWatcherReloadStrategy extends FileWatcherResourceReloadStrateg return "Live route reloading enabled (directory: " + dir + ")"; } - protected void onPropertiesReload(Resource resource) { - LOG.info("Reloading properties: {}. (Only Camel routes can be updated with changes)", + protected void onPropertiesReload(Resource resource) throws Exception { + LOG.info("Reloading properties: {}. (Only Camel routes and components can be updated with changes)", resource.getLocation()); PropertiesComponent pc = getCamelContext().getPropertiesComponent(); boolean reloaded = pc.reloadProperties(resource.getLocation()); if (reloaded) { + PropertiesReload pr = getCamelContext().hasService(PropertiesReload.class); + if (pr != null) { + // load the properties, so we can update (remember location) + InputStream is = resource.getInputStream(); + OrderedProperties tmp = new OrderedProperties(); + tmp.load(is); + IOHelper.close(is); + OrderedLocationProperties properties = new OrderedLocationProperties(); + properties.putAll(resource.getLocation(), tmp); + pr.onReload(resource.getLocation(), properties); + } // trigger all routes to be reloaded onRouteReload(null); }
