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:48 UTC
[camel] 01/04: CAMEL-15784: camel-core - Optimize with Bootstrap
marker interface
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;