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 2020/11/01 18:06:47 UTC

[camel] branch master updated (52ca2a7 -> 1220667e)

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git.


    from 52ca2a7  Sync deps
     new 13472b8  CAMEL-15784: camel-core - Optimize with Bootstrap marker interface
     new f2216e7  Polished
     new eaf32f3  CAMEL-15784: camel-core - Optimize with bootstrap factory finder.
     new 1220667e CAMEL-15784: camel-core - Optimize with bootstrap factory finder.

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../main/java/org/apache/camel/spring/Main.java    |  6 +-
 .../org/apache/camel/ExtendedCamelContext.java     | 21 ++++++
 ...onFactoryAware.java => BootstrapCloseable.java} | 13 ++--
 .../camel/impl/engine/AbstractCamelContext.java    | 45 +++++++++++-
 ...erResolver.java => BootstrapFactoryFinder.java} | 21 ++++--
 .../camel/impl/engine/DefaultFactoryFinder.java    |  6 +-
 .../engine/DefaultServiceBootstrapCloseable.java   | 76 +++++++++++++++++++++
 .../camel/impl/lw/LightweightCamelContext.java     | 17 +++++
 .../impl/lw/LightweightRuntimeCamelContext.java    | 15 ++++
 .../org/apache/camel/main/BaseMainSupport.java     | 64 +++++++++---------
 .../camel/main/DefaultMainShutdownStrategy.java    |  2 +-
 .../FaultToleranceConfigurationProperties.java     | 10 ++-
 .../camel/main/HealthConfigurationProperties.java  | 12 +++-
 .../camel/main/HystrixConfigurationProperties.java | 10 ++-
 .../camel/main/LraConfigurationProperties.java     | 10 ++-
 .../apache/camel/main/MainBootstrapCloseable.java  | 32 +++++++++
 .../apache/camel/main/MainCommandLineSupport.java  | 10 +++
 .../camel/main/MainConfigurationProperties.java    | 79 +++++++++++++++++++---
 .../java/org/apache/camel/main/MainSupport.java    | 28 ++++++--
 .../main/Resilience4jConfigurationProperties.java  | 10 ++-
 .../camel/main/RestConfigurationProperties.java    | 16 ++++-
 .../main/ThreadPoolConfigurationProperties.java    | 12 +++-
 .../camel/main/MainSupportCommandLineTest.java     |  7 +-
 .../main/java/org/apache/camel/util/TimeUtils.java |  4 ++
 24 files changed, 441 insertions(+), 85 deletions(-)
 copy core/camel-api/src/main/java/org/apache/camel/spi/{ExpressionFactoryAware.java => BootstrapCloseable.java} (69%)
 copy core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/{DefaultFactoryFinderResolver.java => BootstrapFactoryFinder.java} (63%)
 create mode 100644 core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultServiceBootstrapCloseable.java
 create mode 100644 core/camel-main/src/main/java/org/apache/camel/main/MainBootstrapCloseable.java


[camel] 04/04: CAMEL-15784: camel-core - Optimize with bootstrap factory finder.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 1220667e1b9cb018f4693369944ae3cd2199b35f
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Nov 1 18:39:30 2020 +0100

    CAMEL-15784: camel-core - Optimize with bootstrap factory finder.
---
 .../main/java/org/apache/camel/impl/engine/AbstractCamelContext.java   | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 29851d3..53974ae 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -3550,7 +3550,8 @@ public abstract class AbstractCamelContext extends BaseService
         ManagementStrategyFactory factory = null;
         if (!isJMXDisabled()) {
             try {
-                FactoryFinder finder = getFactoryFinder("META-INF/services/org/apache/camel/management/");
+                // create a one time factory as we dont need this anymore
+                FactoryFinder finder = createFactoryFinder("META-INF/services/org/apache/camel/management/");
                 if (finder != null) {
                     Object object = finder.newInstance("ManagementStrategyFactory").orElse(null);
                     if (object instanceof ManagementStrategyFactory) {


[camel] 02/04: Polished

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit f2216e7fbd0c2c92f01365e7d024499d554acb85
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Nov 1 17:00:27 2020 +0100

    Polished
---
 .../main/java/org/apache/camel/main/DefaultMainShutdownStrategy.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultMainShutdownStrategy.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultMainShutdownStrategy.java
index 9c353ef..e027a7f 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultMainShutdownStrategy.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultMainShutdownStrategy.java
@@ -98,7 +98,7 @@ public class DefaultMainShutdownStrategy extends SimpleMainShutdownStrategy {
                 while (!main.getCamelContext().isStopped() && !done && watch.taken() < max) {
                     String msg = "Waiting for CamelContext to graceful shutdown, elapsed: "
                                  + TimeUtils.printDuration(watch.taken());
-                    if (waits % 5 == 0) {
+                    if (waits > 0 && waits % 5 == 0) {
                         // do some info logging every 5th time
                         LOG.info(msg);
                     } else {


[camel] 01/04: CAMEL-15784: camel-core - Optimize with Bootstrap marker interface

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 13472b80b91960bd2aea5a20e22790b6e3961c4d
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Nov 1 16:57:08 2020 +0100

    CAMEL-15784: camel-core - Optimize with Bootstrap marker interface
---
 .../main/java/org/apache/camel/spring/Main.java    |  6 +-
 .../org/apache/camel/ExtendedCamelContext.java     | 11 +++
 .../org/apache/camel/spi/BootstrapCloseable.java   | 28 ++++++++
 .../camel/impl/engine/AbstractCamelContext.java    | 28 +++++++-
 .../engine/DefaultServiceBootstrapCloseable.java   | 64 ++++++++++++++++++
 .../camel/impl/lw/LightweightCamelContext.java     | 12 ++++
 .../impl/lw/LightweightRuntimeCamelContext.java    | 10 +++
 .../org/apache/camel/main/BaseMainSupport.java     | 62 +++++++++--------
 .../FaultToleranceConfigurationProperties.java     | 10 ++-
 .../camel/main/HealthConfigurationProperties.java  | 12 +++-
 .../camel/main/HystrixConfigurationProperties.java | 10 ++-
 .../camel/main/LraConfigurationProperties.java     | 10 ++-
 .../apache/camel/main/MainBootstrapCloseable.java  | 32 +++++++++
 .../apache/camel/main/MainCommandLineSupport.java  | 10 +++
 .../camel/main/MainConfigurationProperties.java    | 79 +++++++++++++++++++---
 .../java/org/apache/camel/main/MainSupport.java    | 28 ++++++--
 .../main/Resilience4jConfigurationProperties.java  | 10 ++-
 .../camel/main/RestConfigurationProperties.java    | 16 ++++-
 .../main/ThreadPoolConfigurationProperties.java    | 12 +++-
 .../camel/main/MainSupportCommandLineTest.java     |  7 +-
 .../main/java/org/apache/camel/util/TimeUtils.java |  4 ++
 21 files changed, 397 insertions(+), 64 deletions(-)

diff --git a/components/camel-spring-main/src/main/java/org/apache/camel/spring/Main.java b/components/camel-spring-main/src/main/java/org/apache/camel/spring/Main.java
index 7507fd6..fe34866 100644
--- a/components/camel-spring-main/src/main/java/org/apache/camel/spring/Main.java
+++ b/components/camel-spring-main/src/main/java/org/apache/camel/spring/Main.java
@@ -64,6 +64,11 @@ public class Main extends MainCommandLineSupport {
     private String parentApplicationContextUri;
 
     public Main() {
+    }
+
+    @Override
+    protected void initOptions() {
+        super.initOptions();
 
         addOption(new ParameterOption(
                 "ac", "applicationContext",
@@ -80,7 +85,6 @@ public class Main extends MainCommandLineSupport {
                 setFileApplicationContextUri(parameter);
             }
         });
-
     }
 
     public static void main(String... args) throws Exception {
diff --git a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
index e463e66..f6b1557 100644
--- a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
@@ -27,6 +27,7 @@ import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.spi.BeanProcessorFactory;
 import org.apache.camel.spi.BeanProxyFactory;
+import org.apache.camel.spi.BootstrapCloseable;
 import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.spi.ComponentNameResolver;
 import org.apache.camel.spi.ComponentResolver;
@@ -201,6 +202,16 @@ public interface ExtendedCamelContext extends CamelContext {
     List<RouteStartupOrder> getRouteStartupOrder();
 
     /**
+     * Adds a {@link BootstrapCloseable} task.
+     */
+    void addBootstrap(BootstrapCloseable bootstrap);
+
+    /**
+     * Returns an unmodifiable list of the services registered currently in this {@link CamelContext}.
+     */
+    List<Service> getServices();
+
+    /**
      * Returns the bean post processor used to do any bean customization.
      *
      * @return the bean post processor.
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/BootstrapCloseable.java b/core/camel-api/src/main/java/org/apache/camel/spi/BootstrapCloseable.java
new file mode 100644
index 0000000..cfab0a2
--- /dev/null
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/BootstrapCloseable.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.spi;
+
+import java.io.Closeable;
+
+/**
+ * A marker interface for a service, or other kind of process that is only used during bootstrapping Camel. After the
+ * bootstrap is complete the {@link #close()} method is invoked which allows to do some cleanup processes such as
+ * clearing internal caches, maps etc to clear up memory etc.
+ */
+public interface BootstrapCloseable extends Closeable {
+
+}
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index e6d7fb5..b506a5f 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -79,6 +79,7 @@ import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.spi.BeanProcessorFactory;
 import org.apache.camel.spi.BeanProxyFactory;
+import org.apache.camel.spi.BootstrapCloseable;
 import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.spi.CamelContextNameStrategy;
 import org.apache.camel.spi.CamelContextTracker;
@@ -189,6 +190,7 @@ public abstract class AbstractCamelContext extends BaseService
     private final Map<String, Component> components = new ConcurrentHashMap<>();
     private final Set<Route> routes = new LinkedHashSet<>();
     private final List<Service> servicesToStop = new CopyOnWriteArrayList<>();
+    private final List<BootstrapCloseable> bootstraps = new CopyOnWriteArrayList<>();
     private final List<StartupListener> startupListeners = new CopyOnWriteArrayList<>();
     private final DeferServiceStartupListener deferStartupListener = new DeferServiceStartupListener();
     private final Map<String, Language> languages = new ConcurrentHashMap<>();
@@ -331,7 +333,7 @@ public abstract class AbstractCamelContext extends BaseService
         // create a provisional (temporary) endpoint registry at first since end
         // users may access endpoints before CamelContext is started
         // we will later transfer the endpoints to the actual
-        // DefaultEndpointRegistry later, but we do this to starup Camel faster.
+        // DefaultEndpointRegistry later, but we do this to startup Camel faster.
         this.endpoints = new ProvisionalEndpointRegistry();
 
         // add the defer service startup listener
@@ -343,6 +345,9 @@ public abstract class AbstractCamelContext extends BaseService
         // add a default LifecycleStrategy to customize services using customizers from registry
         this.lifecycleStrategies.add(new CustomizersLifecycleStrategy(this));
 
+        // add the deafult bootstrap
+        this.bootstraps.add(new DefaultServiceBootstrapCloseable(this));
+
         if (build) {
             try {
                 build();
@@ -1438,6 +1443,16 @@ public abstract class AbstractCamelContext extends BaseService
     }
 
     @Override
+    public void addBootstrap(BootstrapCloseable bootstrap) {
+        bootstraps.add(bootstrap);
+    }
+
+    @Override
+    public List<Service> getServices() {
+        return Collections.unmodifiableList(servicesToStop);
+    }
+
+    @Override
     public boolean hasService(Object object) {
         if (servicesToStop.isEmpty()) {
             return false;
@@ -2706,12 +2721,21 @@ public abstract class AbstractCamelContext extends BaseService
             }
             LOG.info("Apache Camel {} ({}) started in {}", getVersion(), getName(), TimeUtils.printDuration(stopWatch.taken()));
 
+            // now Camel has been started/bootstrap is complete, then run cleanup to help free up memory etc
+            for (BootstrapCloseable bootstrap : bootstraps) {
+                try {
+                    bootstrap.close();
+                } catch (Exception e) {
+                    LOG.warn("Error during closing bootstrap. This exception is ignored.", e);
+                }
+            }
+            bootstraps.clear();
+
             if (isLightweight()) {
                 LOG.info(
                         "Lightweight enabled. Clearing services to free memory."
                          + " Danger this impacts the CamelContext not being able to add new routes or use reflection-free configuration, etc.");
                 ReifierStrategy.clearReifiers();
-                ConfigurerStrategy.clearBootstrapConfigurers();
                 ConfigurerStrategy.clearConfigurers();
             }
         }
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultServiceBootstrapCloseable.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultServiceBootstrapCloseable.java
new file mode 100644
index 0000000..411843d
--- /dev/null
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultServiceBootstrapCloseable.java
@@ -0,0 +1,64 @@
+/*
+ * 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.impl.engine;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.Service;
+import org.apache.camel.spi.BootstrapCloseable;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Default {@link BootstrapCloseable} which will collect all registered {@link Service} which is
+ * {@link BootstrapCloseable} and run their task and remove the service from {@link CamelContext}.
+ */
+public class DefaultServiceBootstrapCloseable implements BootstrapCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultServiceBootstrapCloseable.class);
+
+    private final ExtendedCamelContext camelContext;
+
+    public DefaultServiceBootstrapCloseable(CamelContext camelContext) {
+        this.camelContext = (ExtendedCamelContext) camelContext;
+    }
+
+    @Override
+    public void close() {
+        // clear bootstrap configurers
+        ConfigurerStrategy.clearBootstrapConfigurers();
+
+        Set<Service> set
+                = camelContext.getServices().stream().filter(s -> s instanceof BootstrapCloseable).collect(Collectors.toSet());
+        // its a bootstrap service
+        for (Service service : set) {
+            try {
+                if (service instanceof BootstrapCloseable) {
+                    ((BootstrapCloseable) service).close();
+                }
+                // service is no longer needed as it was only intended during bootstrap
+                camelContext.removeService(service);
+            } catch (Exception e) {
+                LOG.warn("Error during closing bootstrap service. This exception is ignored", e);
+            }
+        }
+    }
+}
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 b42f8ed..36ceab9 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
@@ -43,6 +43,7 @@ import org.apache.camel.Processor;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.Route;
 import org.apache.camel.RoutesBuilder;
+import org.apache.camel.Service;
 import org.apache.camel.ServiceStatus;
 import org.apache.camel.ShutdownRoute;
 import org.apache.camel.ShutdownRunningTask;
@@ -74,6 +75,7 @@ import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.spi.BeanProcessorFactory;
 import org.apache.camel.spi.BeanProxyFactory;
 import org.apache.camel.spi.BeanRepository;
+import org.apache.camel.spi.BootstrapCloseable;
 import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.spi.CamelContextNameStrategy;
 import org.apache.camel.spi.ClassResolver;
@@ -344,6 +346,11 @@ public class LightweightCamelContext implements ExtendedCamelContext, CatalogCam
     }
 
     @Override
+    public void addBootstrap(BootstrapCloseable bootstrap) {
+        getExtendedCamelContext().addBootstrap(bootstrap);
+    }
+
+    @Override
     public void addService(Object object) throws Exception {
         delegate.addService(object);
     }
@@ -369,6 +376,11 @@ public class LightweightCamelContext implements ExtendedCamelContext, CatalogCam
     }
 
     @Override
+    public List<Service> getServices() {
+        return getExtendedCamelContext().getServices();
+    }
+
+    @Override
     public boolean hasService(Object object) {
         return delegate.hasService(object);
     }
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
index 387a4d9..93583d8 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
@@ -69,6 +69,7 @@ import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.spi.BeanProcessorFactory;
 import org.apache.camel.spi.BeanProxyFactory;
+import org.apache.camel.spi.BootstrapCloseable;
 import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.spi.CamelContextNameStrategy;
 import org.apache.camel.spi.ClassResolver;
@@ -653,6 +654,15 @@ public class LightweightRuntimeCamelContext implements ExtendedCamelContext, Cat
     }
 
     @Override
+    public void addBootstrap(BootstrapCloseable bootstrap) {
+    }
+
+    @Override
+    public List<Service> getServices() {
+        return null;
+    }
+
+    @Override
     public boolean hasService(Object object) {
         return false;
     }
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 34d541b..9d2a59f 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
@@ -101,8 +101,8 @@ public abstract class BaseMainSupport extends BaseService {
     protected volatile CamelContext camelContext;
 
     protected final List<MainListener> listeners = new ArrayList<>();
-    protected final MainConfigurationProperties mainConfigurationProperties = new MainConfigurationProperties();
-    protected final Properties wildcardProperties = new OrderedProperties();
+    protected MainConfigurationProperties mainConfigurationProperties = new MainConfigurationProperties();
+    protected Properties wildcardProperties = new OrderedProperties();
     protected RoutesCollector routesCollector = new DefaultRoutesCollector();
     protected String propertyPlaceholderLocations;
     protected String defaultPropertyPlaceholderLocation = DEFAULT_PROPERTY_PLACEHOLDER_LOCATION;
@@ -726,54 +726,56 @@ public abstract class BaseMainSupport extends BaseService {
                     mainConfigurationProperties.isAutoConfigurationFailFast(), true, autoConfiguredProperties);
         }
 
-        HystrixConfigurationProperties hystrix = mainConfigurationProperties.hystrix();
         if (!hystrixProperties.isEmpty()) {
+            HystrixConfigurationProperties hystrix = mainConfigurationProperties.hystrix();
             LOG.debug("Auto-configuring Hystrix Circuit Breaker EIP from loaded properties: {}", hystrixProperties.size());
             setPropertiesOnTarget(camelContext, hystrix, hystrixProperties, "camel.hystrix.",
                     mainConfigurationProperties.isAutoConfigurationFailFast(), true, autoConfiguredProperties);
+            HystrixConfigurationDefinition hystrixModel = model.getHystrixConfiguration(null);
+            if (hystrixModel == null) {
+                hystrixModel = new HystrixConfigurationDefinition();
+                model.setHystrixConfiguration(hystrixModel);
+            }
+            if (hystrix != null) {
+                setPropertiesOnTarget(camelContext, hystrixModel, hystrix);
+            }
         }
-        HystrixConfigurationDefinition hystrixModel = model.getHystrixConfiguration(null);
-        if (hystrixModel == null) {
-            hystrixModel = new HystrixConfigurationDefinition();
-            model.setHystrixConfiguration(hystrixModel);
-        }
-        setPropertiesOnTarget(camelContext, hystrixModel, hystrix);
 
-        Resilience4jConfigurationProperties resilience4j = mainConfigurationProperties.resilience4j();
         if (!resilience4jProperties.isEmpty()) {
+            Resilience4jConfigurationProperties resilience4j = mainConfigurationProperties.resilience4j();
             LOG.debug("Auto-configuring Resilience4j Circuit Breaker EIP from loaded properties: {}",
                     resilience4jProperties.size());
             setPropertiesOnTarget(camelContext, resilience4j, resilience4jProperties, "camel.resilience4j.",
                     mainConfigurationProperties.isAutoConfigurationFailFast(), true, autoConfiguredProperties);
+            Resilience4jConfigurationDefinition resilience4jModel = model.getResilience4jConfiguration(null);
+            if (resilience4jModel == null) {
+                resilience4jModel = new Resilience4jConfigurationDefinition();
+                model.setResilience4jConfiguration(resilience4jModel);
+            }
+            setPropertiesOnTarget(camelContext, resilience4jModel, resilience4j);
         }
-        Resilience4jConfigurationDefinition resilience4jModel = model.getResilience4jConfiguration(null);
-        if (resilience4jModel == null) {
-            resilience4jModel = new Resilience4jConfigurationDefinition();
-            model.setResilience4jConfiguration(resilience4jModel);
-        }
-        setPropertiesOnTarget(camelContext, resilience4jModel, resilience4j);
 
-        FaultToleranceConfigurationProperties faultTolerance = mainConfigurationProperties.faultTolerance();
         if (!faultToleranceProperties.isEmpty()) {
+            FaultToleranceConfigurationProperties faultTolerance = mainConfigurationProperties.faultTolerance();
             LOG.debug("Auto-configuring MicroProfile Fault Tolerance Circuit Breaker EIP from loaded properties: {}",
                     faultToleranceProperties.size());
             setPropertiesOnTarget(camelContext, faultTolerance, faultToleranceProperties, "camel.faulttolerance.",
                     mainConfigurationProperties.isAutoConfigurationFailFast(), true, autoConfiguredProperties);
+            FaultToleranceConfigurationDefinition faultToleranceModel = model.getFaultToleranceConfiguration(null);
+            if (faultToleranceModel == null) {
+                faultToleranceModel = new FaultToleranceConfigurationDefinition();
+                model.setFaultToleranceConfiguration(faultToleranceModel);
+            }
+            setPropertiesOnTarget(camelContext, faultToleranceModel, faultTolerance);
         }
-        FaultToleranceConfigurationDefinition faultToleranceModel = model.getFaultToleranceConfiguration(null);
-        if (faultToleranceModel == null) {
-            faultToleranceModel = new FaultToleranceConfigurationDefinition();
-            model.setFaultToleranceConfiguration(faultToleranceModel);
-        }
-        setPropertiesOnTarget(camelContext, faultToleranceModel, faultTolerance);
 
-        RestConfigurationProperties rest = mainConfigurationProperties.rest();
         if (!restProperties.isEmpty()) {
+            RestConfigurationProperties rest = mainConfigurationProperties.rest();
             LOG.debug("Auto-configuring Rest DSL from loaded properties: {}", restProperties.size());
             setPropertiesOnTarget(camelContext, rest, restProperties, "camel.rest.",
                     mainConfigurationProperties.isAutoConfigurationFailFast(), true, autoConfiguredProperties);
+            camelContext.setRestConfiguration(rest);
         }
-        camelContext.setRestConfiguration(rest);
 
         if (!threadPoolProperties.isEmpty()) {
             LOG.debug("Auto-configuring Thread Pool from loaded properties: {}", threadPoolProperties.size());
@@ -804,27 +806,27 @@ public abstract class BaseMainSupport extends BaseService {
         }
         if (!contextProperties.isEmpty()) {
             contextProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.context.{}={} on bean: {}", k, v, camelContext);
+                LOG.warn("Property not auto-configured: camel.context.{}={}", k, v);
             });
         }
         if (!hystrixProperties.isEmpty()) {
             hystrixProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.hystrix.{}={} on bean: {}", k, v, hystrix);
+                LOG.warn("Property not auto-configured: camel.hystrix.{}={}", k, v);
             });
         }
         if (!resilience4jProperties.isEmpty()) {
             resilience4jProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.resilience4j.{}={} on bean: {}", k, v, resilience4j);
+                LOG.warn("Property not auto-configured: camel.resilience4j.{}={}", k, v);
             });
         }
         if (!faultToleranceProperties.isEmpty()) {
             faultToleranceProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.faulttolerance.{}={} on bean: {}", k, v, faultTolerance);
+                LOG.warn("Property not auto-configured: camel.faulttolerance.{}={}", k, v);
             });
         }
         if (!restProperties.isEmpty()) {
             restProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.rest.{}={} on bean: {}", k, v, rest);
+                LOG.warn("Property not auto-configured: camel.rest.{}={}", k, v);
             });
         }
         if (!threadPoolProperties.isEmpty()) {
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/FaultToleranceConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/FaultToleranceConfigurationProperties.java
index 601a25b..a242748 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/FaultToleranceConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/FaultToleranceConfigurationProperties.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.main;
 
+import org.apache.camel.spi.BootstrapCloseable;
 import org.apache.camel.spi.Configurer;
 import org.apache.camel.spi.Metadata;
 
@@ -23,9 +24,9 @@ import org.apache.camel.spi.Metadata;
  * Global configuration for MicroProfile Fault Tolerance EIP circuit breaker.
  */
 @Configurer(bootstrap = true)
-public class FaultToleranceConfigurationProperties {
+public class FaultToleranceConfigurationProperties implements BootstrapCloseable {
 
-    private final MainConfigurationProperties parent;
+    private MainConfigurationProperties parent;
 
     private String circuitBreakerRef;
     @Metadata(defaultValue = "5")
@@ -59,6 +60,11 @@ public class FaultToleranceConfigurationProperties {
         return parent;
     }
 
+    @Override
+    public void close() {
+        parent = null;
+    }
+
     // getter and setters
     // --------------------------------------------------------------
 
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/HealthConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/HealthConfigurationProperties.java
index 1c212f0..b652291 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/HealthConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/HealthConfigurationProperties.java
@@ -19,6 +19,7 @@ package org.apache.camel.main;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.camel.spi.BootstrapCloseable;
 import org.apache.camel.spi.Configurer;
 import org.apache.camel.spi.Metadata;
 
@@ -26,9 +27,9 @@ import org.apache.camel.spi.Metadata;
  * Global configuration for Health Check
  */
 @Configurer(bootstrap = true)
-public class HealthConfigurationProperties {
+public class HealthConfigurationProperties implements BootstrapCloseable {
 
-    private final MainConfigurationProperties parent;
+    private MainConfigurationProperties parent;
 
     @Metadata(defaultValue = "true")
     private Boolean enabled;
@@ -48,6 +49,13 @@ public class HealthConfigurationProperties {
         return parent;
     }
 
+    @Override
+    public void close() {
+        config.clear();
+        config = null;
+        parent = null;
+    }
+
     public Boolean getEnabled() {
         return enabled;
     }
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/HystrixConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/HystrixConfigurationProperties.java
index c725f73..fcb2f53 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/HystrixConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/HystrixConfigurationProperties.java
@@ -21,6 +21,7 @@ import java.util.concurrent.Future;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.camel.spi.BootstrapCloseable;
 import org.apache.camel.spi.Configurer;
 
 /**
@@ -28,9 +29,9 @@ import org.apache.camel.spi.Configurer;
  */
 @Configurer(bootstrap = true)
 @Deprecated
-public class HystrixConfigurationProperties {
+public class HystrixConfigurationProperties implements BootstrapCloseable {
 
-    private final MainConfigurationProperties parent;
+    private MainConfigurationProperties parent;
 
     private String groupKey;
     private String threadPoolKey;
@@ -73,6 +74,11 @@ public class HystrixConfigurationProperties {
         return parent;
     }
 
+    @Override
+    public void close() {
+        parent = null;
+    }
+
     // getter and setters
     // --------------------------------------------------------------
 
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/LraConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/LraConfigurationProperties.java
index 134f71f..c0106dd 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/LraConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/LraConfigurationProperties.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.main;
 
+import org.apache.camel.spi.BootstrapCloseable;
 import org.apache.camel.spi.Configurer;
 import org.apache.camel.spi.Metadata;
 
@@ -23,9 +24,9 @@ import org.apache.camel.spi.Metadata;
  * Global configuration for Saga LRA
  */
 @Configurer(bootstrap = true)
-public class LraConfigurationProperties {
+public class LraConfigurationProperties implements BootstrapCloseable {
 
-    private final MainConfigurationProperties parent;
+    private MainConfigurationProperties parent;
 
     private String coordinatorUrl;
     @Metadata(defaultValue = "/lra-coordinator")
@@ -42,6 +43,11 @@ public class LraConfigurationProperties {
         return parent;
     }
 
+    @Override
+    public void close() {
+        parent = null;
+    }
+
     public String getCoordinatorUrl() {
         return coordinatorUrl;
     }
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainBootstrapCloseable.java b/core/camel-main/src/main/java/org/apache/camel/main/MainBootstrapCloseable.java
new file mode 100644
index 0000000..8d7ba90
--- /dev/null
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainBootstrapCloseable.java
@@ -0,0 +1,32 @@
+package org.apache.camel.main;
+
+import org.apache.camel.spi.BootstrapCloseable;
+
+public class MainBootstrapCloseable implements BootstrapCloseable {
+
+    private final MainSupport main;
+
+    public MainBootstrapCloseable(MainSupport main) {
+        this.main = main;
+    }
+
+    @Override
+    public void close() {
+        // we are now bootstrapped and can clear up memory
+        if (main.initialProperties != null) {
+            main.initialProperties.clear();
+            main.initialProperties = null;
+        }
+        if (main.overrideProperties != null) {
+            main.overrideProperties.clear();
+            main.overrideProperties = null;
+        }
+        main.wildcardProperties.clear();
+        main.wildcardProperties = null;
+
+        // no longer in use
+        main.mainConfigurationProperties.close();
+        main.mainConfigurationProperties = null;
+        main.routesCollector = null;
+    }
+}
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainCommandLineSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/MainCommandLineSupport.java
index 231b020..e82a7f0 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainCommandLineSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainCommandLineSupport.java
@@ -27,12 +27,19 @@ import java.util.List;
 public abstract class MainCommandLineSupport extends MainSupport {
 
     protected final List<Option> options = new ArrayList<>();
+    private volatile boolean initOptionsDone;
 
     public MainCommandLineSupport(Class... configurationClasses) {
         super(configurationClasses);
     }
 
     public MainCommandLineSupport() {
+    }
+
+    protected void initOptions() {
+        if (initOptionsDone) {
+            return;
+        }
         addOption(new Option("h", "help", "Displays the help screen") {
             protected void doProcess(String arg, LinkedList<String> remainingArgs) {
                 showOptions();
@@ -101,12 +108,14 @@ public abstract class MainCommandLineSupport extends MainSupport {
                 setPropertyPlaceholderLocations(parameter);
             }
         });
+        initOptionsDone = true;
     }
 
     /**
      * Displays the command line options.
      */
     public void showOptions() {
+        initOptions();
         showOptionsHeader();
 
         for (Option option : options) {
@@ -122,6 +131,7 @@ public abstract class MainCommandLineSupport extends MainSupport {
 
         boolean valid = true;
         while (!args.isEmpty()) {
+            initOptions();
             String arg = args.removeFirst();
 
             boolean handled = false;
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
index 02b09ac..ba4298a 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
@@ -22,13 +22,15 @@ import java.util.List;
 import org.apache.camel.RoutesBuilder;
 import org.apache.camel.builder.LambdaRouteBuilder;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spi.BootstrapCloseable;
 import org.apache.camel.spi.Configurer;
 
 /**
  * Global configuration for Camel Main to setup context name, stream caching and other global configurations.
  */
 @Configurer(bootstrap = true)
-public class MainConfigurationProperties extends DefaultConfigurationProperties<MainConfigurationProperties> {
+public class MainConfigurationProperties extends DefaultConfigurationProperties<MainConfigurationProperties>
+        implements BootstrapCloseable {
 
     private boolean autoConfigurationEnabled = true;
     private boolean autoConfigurationEnvironmentVariablesEnabled = true;
@@ -48,15 +50,49 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
     private List<Object> configurations = new ArrayList<>();
 
     // extended configuration
-    private final HealthConfigurationProperties healthConfigurationProperties = new HealthConfigurationProperties(this);
-    private final LraConfigurationProperties lraConfigurationProperties = new LraConfigurationProperties(this);
-    private final ThreadPoolConfigurationProperties threadPool = new ThreadPoolConfigurationProperties(this);
-    private final HystrixConfigurationProperties hystrixConfigurationProperties = new HystrixConfigurationProperties(this);
-    private final Resilience4jConfigurationProperties resilience4jConfigurationProperties
-            = new Resilience4jConfigurationProperties(this);
-    private final FaultToleranceConfigurationProperties faultToleranceConfigurationProperties
-            = new FaultToleranceConfigurationProperties(this);
-    private final RestConfigurationProperties restConfigurationProperties = new RestConfigurationProperties(this);
+    private HealthConfigurationProperties healthConfigurationProperties;
+    private LraConfigurationProperties lraConfigurationProperties;
+    private ThreadPoolConfigurationProperties threadPool;
+    private HystrixConfigurationProperties hystrixConfigurationProperties;
+    private Resilience4jConfigurationProperties resilience4jConfigurationProperties;
+    private FaultToleranceConfigurationProperties faultToleranceConfigurationProperties;
+    private RestConfigurationProperties restConfigurationProperties;
+
+    @Override
+    public void close() {
+        if (healthConfigurationProperties != null) {
+            healthConfigurationProperties.close();
+            healthConfigurationProperties = null;
+        }
+        if (lraConfigurationProperties != null) {
+            lraConfigurationProperties.close();
+            lraConfigurationProperties = null;
+        }
+        if (threadPool != null) {
+            threadPool.close();
+            threadPool = null;
+        }
+        if (hystrixConfigurationProperties != null) {
+            hystrixConfigurationProperties.close();
+            hystrixConfigurationProperties = null;
+        }
+        if (resilience4jConfigurationProperties != null) {
+            resilience4jConfigurationProperties.close();
+            resilience4jConfigurationProperties = null;
+        }
+        if (faultToleranceConfigurationProperties != null) {
+            faultToleranceConfigurationProperties.close();
+            faultToleranceConfigurationProperties = null;
+        }
+        if (restConfigurationProperties != null) {
+            restConfigurationProperties.close();
+            restConfigurationProperties = null;
+        }
+        routesBuilders.clear();
+        routesBuilders = null;
+        configurations.clear();
+        configurations = null;
+    }
 
     // extended
     // --------------------------------------------------------------
@@ -65,6 +101,9 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
      * To configure Health Check
      */
     public HealthConfigurationProperties health() {
+        if (healthConfigurationProperties == null) {
+            healthConfigurationProperties = new HealthConfigurationProperties(this);
+        }
         return healthConfigurationProperties;
     }
 
@@ -72,6 +111,9 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
      * To configure Saga LRA
      */
     public LraConfigurationProperties lra() {
+        if (lraConfigurationProperties == null) {
+            lraConfigurationProperties = new LraConfigurationProperties(this);
+        }
         return lraConfigurationProperties;
     }
 
@@ -79,6 +121,9 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
      * To configure thread pools
      */
     public ThreadPoolConfigurationProperties threadPool() {
+        if (threadPool == null) {
+            threadPool = new ThreadPoolConfigurationProperties(this);
+        }
         return threadPool;
     }
 
@@ -87,6 +132,9 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
      */
     @Deprecated
     public HystrixConfigurationProperties hystrix() {
+        if (hystrixConfigurationProperties == null) {
+            hystrixConfigurationProperties = new HystrixConfigurationProperties(this);
+        }
         return hystrixConfigurationProperties;
     }
 
@@ -94,6 +142,9 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
      * To configure Circuit Breaker EIP with Resilience4j
      */
     public Resilience4jConfigurationProperties resilience4j() {
+        if (resilience4jConfigurationProperties == null) {
+            resilience4jConfigurationProperties = new Resilience4jConfigurationProperties(this);
+        }
         return resilience4jConfigurationProperties;
     }
 
@@ -101,6 +152,9 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
      * To configure Circuit Breaker EIP with MicroProfile Fault Tolerance
      */
     public FaultToleranceConfigurationProperties faultTolerance() {
+        if (faultToleranceConfigurationProperties == null) {
+            faultToleranceConfigurationProperties = new FaultToleranceConfigurationProperties(this);
+        }
         return faultToleranceConfigurationProperties;
     }
 
@@ -108,6 +162,9 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
      * To configure Rest DSL
      */
     public RestConfigurationProperties rest() {
+        if (restConfigurationProperties == null) {
+            restConfigurationProperties = new RestConfigurationProperties(this);
+        }
         return restConfigurationProperties;
     }
 
@@ -355,7 +412,7 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
             existing = "";
         }
         if (routeBuilder != null) {
-            for (Class clazz : routeBuilder) {
+            for (Class<?> clazz : routeBuilder) {
                 if (!existing.isEmpty()) {
                     existing = existing + ",";
                 }
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
index 3176f8d..ee4618e 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
@@ -20,6 +20,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.spi.EventNotifier;
 import org.apache.camel.support.service.ServiceHelper;
@@ -41,6 +42,11 @@ public abstract class MainSupport extends BaseMainSupport {
 
     protected volatile ProducerTemplate camelTemplate;
 
+    private int durationMaxIdleSeconds;
+    private int durationMaxMessages;
+    private long durationMaxSeconds;
+    private int durationHitExitCode;
+
     protected MainSupport(Class<?>... configurationClasses) {
         this();
         configure().addConfigurationClass(configurationClasses);
@@ -97,6 +103,17 @@ public abstract class MainSupport extends BaseMainSupport {
     }
 
     private void internalBeforeStart() {
+        // used while waiting to be done
+        durationMaxIdleSeconds = mainConfigurationProperties.getDurationMaxIdleSeconds();
+        durationMaxMessages = mainConfigurationProperties.getDurationMaxMessages();
+        durationMaxSeconds = mainConfigurationProperties.getDurationMaxSeconds();
+        durationHitExitCode = mainConfigurationProperties.getDurationHitExitCode();
+
+        // register main as bootstrap
+        CamelContext context = getCamelContext();
+        if (context != null) {
+            context.adapt(ExtendedCamelContext.class).addBootstrap(new MainBootstrapCloseable(this));
+        }
     }
 
     /**
@@ -271,13 +288,14 @@ public abstract class MainSupport extends BaseMainSupport {
     protected void waitUntilCompleted() {
         while (shutdownStrategy.isRunAllowed()) {
             try {
-                int idle = mainConfigurationProperties.getDurationMaxIdleSeconds();
-                int max = mainConfigurationProperties.getDurationMaxMessages();
-                long sec = mainConfigurationProperties.getDurationMaxSeconds();
+                int idle = durationMaxIdleSeconds;
+                int max = durationMaxMessages;
+                long sec = durationMaxSeconds;
+                int exit = durationHitExitCode;
                 if (sec > 0) {
                     LOG.info("Waiting for: {} seconds", sec);
                     shutdownStrategy.await(sec, TimeUnit.SECONDS);
-                    exitCode.compareAndSet(UNINITIALIZED_EXIT_CODE, mainConfigurationProperties.getDurationHitExitCode());
+                    exitCode.compareAndSet(UNINITIALIZED_EXIT_CODE, exit);
                     shutdownStrategy.shutdown();
                 } else if (idle > 0 || max > 0) {
                     if (idle > 0 && max > 0) {
@@ -287,7 +305,7 @@ public abstract class MainSupport extends BaseMainSupport {
                     } else {
                         LOG.info("Waiting until: {} messages has been processed", max);
                     }
-                    exitCode.compareAndSet(UNINITIALIZED_EXIT_CODE, mainConfigurationProperties.getDurationHitExitCode());
+                    exitCode.compareAndSet(UNINITIALIZED_EXIT_CODE, exit);
                     shutdownStrategy.await();
                     shutdownStrategy.shutdown();
                 } else {
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/Resilience4jConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/Resilience4jConfigurationProperties.java
index b619e27..caeca39 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/Resilience4jConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/Resilience4jConfigurationProperties.java
@@ -18,6 +18,7 @@ package org.apache.camel.main;
 
 import java.util.concurrent.ForkJoinPool;
 
+import org.apache.camel.spi.BootstrapCloseable;
 import org.apache.camel.spi.Configurer;
 import org.apache.camel.spi.Metadata;
 
@@ -25,9 +26,9 @@ import org.apache.camel.spi.Metadata;
  * Global configuration for Resilience EIP circuit breaker.
  */
 @Configurer(bootstrap = true)
-public class Resilience4jConfigurationProperties {
+public class Resilience4jConfigurationProperties implements BootstrapCloseable {
 
-    private final MainConfigurationProperties parent;
+    private MainConfigurationProperties parent;
 
     private String circuitBreakerRef;
     private String configRef;
@@ -69,6 +70,11 @@ public class Resilience4jConfigurationProperties {
         return parent;
     }
 
+    @Override
+    public void close() {
+        parent = null;
+    }
+
     // getter and setters
     // --------------------------------------------------------------
 
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/RestConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/RestConfigurationProperties.java
index 3f7e762..959e60e 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/RestConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/RestConfigurationProperties.java
@@ -18,6 +18,7 @@ package org.apache.camel.main;
 
 import java.util.HashMap;
 
+import org.apache.camel.spi.BootstrapCloseable;
 import org.apache.camel.spi.Configurer;
 import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.support.PatternHelper;
@@ -26,9 +27,9 @@ import org.apache.camel.support.PatternHelper;
  * Global configuration for Rest DSL.
  */
 @Configurer(bootstrap = true)
-public class RestConfigurationProperties extends RestConfiguration {
+public class RestConfigurationProperties extends RestConfiguration implements BootstrapCloseable {
 
-    private final MainConfigurationProperties parent;
+    private MainConfigurationProperties parent;
 
     public RestConfigurationProperties(MainConfigurationProperties parent) {
         this.parent = parent;
@@ -38,6 +39,17 @@ public class RestConfigurationProperties extends RestConfiguration {
         return parent;
     }
 
+    @Override
+    public void close() {
+        parent = null;
+        setComponentProperties(null);
+        setEndpointProperties(null);
+        setConsumerProperties(null);
+        setDataFormatProperties(null);
+        setApiProperties(null);
+        setCorsHeaders(null);
+    }
+
     // getter and setters
     // --------------------------------------------------------------
 
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/ThreadPoolConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/ThreadPoolConfigurationProperties.java
index 136c55a..d37d140 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/ThreadPoolConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/ThreadPoolConfigurationProperties.java
@@ -20,6 +20,7 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.camel.spi.BootstrapCloseable;
 import org.apache.camel.spi.Configurer;
 import org.apache.camel.util.concurrent.ThreadPoolRejectedPolicy;
 
@@ -27,9 +28,9 @@ import org.apache.camel.util.concurrent.ThreadPoolRejectedPolicy;
  * Global configuration for thread pools
  */
 @Configurer(bootstrap = true)
-public class ThreadPoolConfigurationProperties {
+public class ThreadPoolConfigurationProperties implements BootstrapCloseable {
 
-    private final MainConfigurationProperties parent;
+    private MainConfigurationProperties parent;
 
     // default values
     private Integer poolSize;
@@ -51,6 +52,13 @@ public class ThreadPoolConfigurationProperties {
         return parent;
     }
 
+    @Override
+    public void close() {
+        parent = null;
+        config.clear();
+        config = null;
+    }
+
     public Integer getPoolSize() {
         return poolSize;
     }
diff --git a/core/camel-main/src/test/java/org/apache/camel/main/MainSupportCommandLineTest.java b/core/camel-main/src/test/java/org/apache/camel/main/MainSupportCommandLineTest.java
index 50e7b53..f483187 100644
--- a/core/camel-main/src/test/java/org/apache/camel/main/MainSupportCommandLineTest.java
+++ b/core/camel-main/src/test/java/org/apache/camel/main/MainSupportCommandLineTest.java
@@ -34,7 +34,12 @@ public class MainSupportCommandLineTest {
 
         @Override
         protected CamelContext createCamelContext() {
-            return null;
+            return context;
+        }
+
+        @Override
+        public CamelContext getCamelContext() {
+            return context;
         }
     }
 
diff --git a/core/camel-util/src/main/java/org/apache/camel/util/TimeUtils.java b/core/camel-util/src/main/java/org/apache/camel/util/TimeUtils.java
index aacd7c7..13daedc 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/TimeUtils.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/TimeUtils.java
@@ -57,6 +57,10 @@ public final class TimeUtils {
      * @return         the time used for displaying on screen or in logs
      */
     public static String printDuration(long uptime, boolean precise) {
+        if (uptime <= 0) {
+            return "0ms";
+        }
+
         StringBuilder sb = new StringBuilder();
 
         long seconds = uptime / 1000;


[camel] 03/04: CAMEL-15784: camel-core - Optimize with bootstrap factory finder.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit eaf32f3ad9ec2e628050a3fff98692ecba43a286
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Nov 1 17:24:41 2020 +0100

    CAMEL-15784: camel-core - Optimize with bootstrap factory finder.
---
 .../org/apache/camel/ExtendedCamelContext.java     | 10 ++++++
 .../camel/impl/engine/AbstractCamelContext.java    | 14 ++++++++
 .../camel/impl/engine/BootstrapFactoryFinder.java  | 40 ++++++++++++++++++++++
 .../camel/impl/engine/DefaultFactoryFinder.java    |  6 ++--
 .../engine/DefaultServiceBootstrapCloseable.java   | 12 +++++++
 .../camel/impl/lw/LightweightCamelContext.java     |  5 +++
 .../impl/lw/LightweightRuntimeCamelContext.java    |  5 +++
 .../org/apache/camel/main/BaseMainSupport.java     |  2 +-
 8 files changed, 90 insertions(+), 4 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
index f6b1557..4cd561b 100644
--- a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
@@ -329,10 +329,20 @@ public interface ExtendedCamelContext extends CamelContext {
      * Gets the default FactoryFinder which will be used for the loading the factory class from META-INF
      *
      * @return the default factory finder
+     * @see    #getBootstrapFactoryFinder()
      */
     FactoryFinder getDefaultFactoryFinder();
 
     /**
+     * Gets the bootstrap FactoryFinder which will be used for the loading the factory class from META-INF. This
+     * bootstrap factory finder is only intended to be used during bootstrap (starting) CamelContext.
+     *
+     * @return the bootstrap factory finder
+     * @see    #getDefaultFactoryFinder()
+     */
+    FactoryFinder getBootstrapFactoryFinder();
+
+    /**
      * Gets the FactoryFinder which will be used for the loading the factory class from META-INF in the given path
      *
      * @param  path the META-INF path
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index b506a5f..29851d3 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -199,6 +199,7 @@ public abstract class AbstractCamelContext extends BaseService
     private final ThreadLocal<Boolean> isStartingRoutes = new ThreadLocal<>();
     private final ThreadLocal<Boolean> isSetupRoutes = new ThreadLocal<>();
     private final Map<String, FactoryFinder> factories = new ConcurrentHashMap<>();
+    private FactoryFinder bootstrapFactoryFinder;
     private final Map<String, RouteService> routeServices = new LinkedHashMap<>();
     private final Map<String, RouteService> suspendedRouteServices = new LinkedHashMap<>();
     private final Object lock = new Object();
@@ -3281,6 +3282,7 @@ public abstract class AbstractCamelContext extends BaseService
     protected void doStartEagerServices() {
         getFactoryFinderResolver();
         getDefaultFactoryFinder();
+        getBootstrapFactoryFinder();
         getComponentResolver();
         getComponentNameResolver();
         getDataFormatResolver();
@@ -3376,6 +3378,18 @@ public abstract class AbstractCamelContext extends BaseService
     }
 
     @Override
+    public FactoryFinder getBootstrapFactoryFinder() {
+        if (bootstrapFactoryFinder == null) {
+            synchronized (lock) {
+                if (bootstrapFactoryFinder == null) {
+                    bootstrapFactoryFinder = new BootstrapFactoryFinder(getClassResolver(), FactoryFinder.DEFAULT_PATH);
+                }
+            }
+        }
+        return bootstrapFactoryFinder;
+    }
+
+    @Override
     public FactoryFinderResolver getFactoryFinderResolver() {
         if (factoryFinderResolver == null) {
             synchronized (lock) {
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/BootstrapFactoryFinder.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/BootstrapFactoryFinder.java
new file mode 100644
index 0000000..bd017ed
--- /dev/null
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/BootstrapFactoryFinder.java
@@ -0,0 +1,40 @@
+/*
+ * 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.impl.engine;
+
+import org.apache.camel.spi.BootstrapCloseable;
+import org.apache.camel.spi.ClassResolver;
+
+/**
+ * Bootstrap factory finder.
+ */
+public class BootstrapFactoryFinder extends DefaultFactoryFinder implements BootstrapCloseable {
+
+    public BootstrapFactoryFinder(ClassResolver classResolver, String resourcePath) {
+        super(classResolver, resourcePath);
+    }
+
+    @Override
+    public void close() {
+        classMap.clear();
+        classMap = null;
+        classesNotFound.clear();
+        classesNotFound = null;
+        classesNotFoundExceptions.clear();
+        classesNotFoundExceptions = null;
+    }
+}
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultFactoryFinder.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultFactoryFinder.java
index bd4f64e..818450b 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultFactoryFinder.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultFactoryFinder.java
@@ -36,9 +36,9 @@ import org.apache.camel.util.IOHelper;
  */
 public class DefaultFactoryFinder implements FactoryFinder {
 
-    private final ConcurrentMap<String, Class<?>> classMap = new ConcurrentHashMap<>();
-    private final ConcurrentMap<String, Boolean> classesNotFound = new ConcurrentHashMap<>();
-    private final ConcurrentMap<String, Exception> classesNotFoundExceptions = new ConcurrentHashMap<>();
+    protected ConcurrentMap<String, Class<?>> classMap = new ConcurrentHashMap<>();
+    protected ConcurrentMap<String, Boolean> classesNotFound = new ConcurrentHashMap<>();
+    protected ConcurrentMap<String, Exception> classesNotFoundExceptions = new ConcurrentHashMap<>();
     private final ClassResolver classResolver;
     private final String path;
 
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultServiceBootstrapCloseable.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultServiceBootstrapCloseable.java
index 411843d..974a67d 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultServiceBootstrapCloseable.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultServiceBootstrapCloseable.java
@@ -24,6 +24,7 @@ import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.Service;
 import org.apache.camel.spi.BootstrapCloseable;
 import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.FactoryFinder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -60,5 +61,16 @@ public class DefaultServiceBootstrapCloseable implements BootstrapCloseable {
                 LOG.warn("Error during closing bootstrap service. This exception is ignored", e);
             }
         }
+
+        // clear bootstrap factory finder
+        FactoryFinder ff = camelContext.getBootstrapFactoryFinder();
+        if (ff instanceof BootstrapCloseable) {
+            try {
+                ((BootstrapCloseable) ff).close();
+            } catch (Exception e) {
+                LOG.warn("Error during closing bootstrap service. This exception is ignored", e);
+            }
+        }
     }
+
 }
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 36ceab9..9478987 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
@@ -1226,6 +1226,11 @@ public class LightweightCamelContext implements ExtendedCamelContext, CatalogCam
     }
 
     @Override
+    public FactoryFinder getBootstrapFactoryFinder() {
+        return getExtendedCamelContext().getBootstrapFactoryFinder();
+    }
+
+    @Override
     public FactoryFinder getFactoryFinder(String path) {
         return getExtendedCamelContext().getFactoryFinder(path);
     }
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
index 93583d8..4dbabdf 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
@@ -1364,6 +1364,11 @@ public class LightweightRuntimeCamelContext implements ExtendedCamelContext, Cat
     }
 
     @Override
+    public FactoryFinder getBootstrapFactoryFinder() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public FactoryFinder getFactoryFinder(String path) {
         throw new UnsupportedOperationException();
     }
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 9d2a59f..bf411a6 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
@@ -1052,7 +1052,7 @@ public abstract class BaseMainSupport extends BaseService {
         if (set.size() == 1) {
             return set.iterator().next();
         }
-        CamelSagaService answer = camelContext.adapt(ExtendedCamelContext.class).getDefaultFactoryFinder()
+        CamelSagaService answer = camelContext.adapt(ExtendedCamelContext.class).getBootstrapFactoryFinder()
                 .newInstance("lra-saga-service", CamelSagaService.class)
                 .orElseThrow(() -> new IllegalArgumentException(
                         "Cannot find LRASagaService on classpath. "