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 ec6c9274787d2ada1bb02858804e91ead2f5eb00 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Mon Jun 8 12:51:30 2020 +0200 camel-health - configuration properties class. --- .../camel/health/HealthCheckConfiguration.java | 49 ++++-- ...althCheckConfigurationPropertiesConfigurer.java | 60 ++++++++ .../camel-main-configuration-metadata.json | 10 +- .../configurer/HealthCheckConfigurationProperties | 2 + .../org/apache/camel/main/BaseMainSupport.java | 169 ++++++--------------- .../camel/main/DefaultConfigurationConfigurer.java | 6 +- .../main/HealthCheckConfigurationProperties.java | 9 ++ .../camel/main/HealthConfigurationProperties.java | 96 ++++++++---- 8 files changed, 230 insertions(+), 171 deletions(-) diff --git a/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckConfiguration.java b/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckConfiguration.java index cd02395..996e24a 100644 --- a/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckConfiguration.java +++ b/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckConfiguration.java @@ -22,31 +22,40 @@ import org.apache.camel.RuntimeCamelException; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.TimeUtils; +/** + * Configuration for {@link HealthCheck}. + */ public class HealthCheckConfiguration implements Cloneable { - /** - * Set if the check associated to this configuration is enabled or not. - */ + private String parent; private boolean enabled = true; - - /** - * Set the check interval in milli seconds. - */ private long interval; - - /** - * Set the number of failure before reporting the service as un-healthy. - */ private int failureThreshold; // ************************************************* // Properties // ************************************************* + public String getParent() { + return parent; + } + + /** + * The id of the health check such as routes or registry (can use * as wildcard) + */ + public void setParent(String parent) { + this.parent = parent; + } + public boolean isEnabled() { return enabled; } + /** + * Set if the check associated to this configuration is enabled or not. + * + * Is default enabled. + */ public void setEnabled(boolean enabled) { this.enabled = enabled; } @@ -55,6 +64,9 @@ public class HealthCheckConfiguration implements Cloneable { return interval; } + /** + * Set the check interval in milli seconds. + */ public void setInterval(long interval) { this.interval = interval; } @@ -63,6 +75,9 @@ public class HealthCheckConfiguration implements Cloneable { return failureThreshold; } + /** + * Set the number of failure before reporting the service as un-healthy. + */ public void setFailureThreshold(int failureThreshold) { this.failureThreshold = failureThreshold; } @@ -84,6 +99,7 @@ public class HealthCheckConfiguration implements Cloneable { // ************************************************* public static final class Builder implements org.apache.camel.Builder<HealthCheckConfiguration> { + private String parent; private Boolean enabled; private Long interval; private Integer failureThreshold; @@ -93,6 +109,9 @@ public class HealthCheckConfiguration implements Cloneable { public Builder complete(HealthCheckConfiguration template) { if (template != null) { + if (this.parent == null) { + this.parent = template.parent; + } if (this.enabled == null) { this.enabled = template.enabled; } @@ -107,6 +126,11 @@ public class HealthCheckConfiguration implements Cloneable { return this; } + public Builder parent(String parent) { + this.parent = parent; + return this; + } + public Builder enabled(boolean enabled) { this.enabled = enabled; return this; @@ -136,6 +160,9 @@ public class HealthCheckConfiguration implements Cloneable { @Override public HealthCheckConfiguration build() { HealthCheckConfiguration conf = new HealthCheckConfiguration(); + if (parent != null) { + conf.setParent(parent); + } if (enabled != null) { conf.setEnabled(enabled); } diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/HealthCheckConfigurationPropertiesConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/HealthCheckConfigurationPropertiesConfigurer.java new file mode 100644 index 0000000..8e03776 --- /dev/null +++ b/core/camel-main/src/generated/java/org/apache/camel/main/HealthCheckConfigurationPropertiesConfigurer.java @@ -0,0 +1,60 @@ +/* Generated by camel build tools - do NOT edit this file! */ +package org.apache.camel.main; + +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.spi.GeneratedPropertyConfigurer; +import org.apache.camel.spi.PropertyConfigurerGetter; +import org.apache.camel.util.CaseInsensitiveMap; +import org.apache.camel.main.HealthCheckConfigurationProperties; + +/** + * Generated by camel build tools - do NOT edit this file! + */ +@SuppressWarnings("unchecked") +public class HealthCheckConfigurationPropertiesConfigurer extends org.apache.camel.support.component.PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter { + + @Override + public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) { + org.apache.camel.main.HealthCheckConfigurationProperties target = (org.apache.camel.main.HealthCheckConfigurationProperties) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "enabled": + case "Enabled": target.setEnabled(property(camelContext, boolean.class, value)); return true; + case "failurethreshold": + case "FailureThreshold": target.setFailureThreshold(property(camelContext, int.class, value)); return true; + case "interval": + case "Interval": target.setInterval(property(camelContext, long.class, value)); return true; + case "parent": + case "Parent": target.setParent(property(camelContext, java.lang.String.class, value)); return true; + default: return false; + } + } + + @Override + public Map<String, Object> getAllOptions(Object target) { + Map<String, Object> answer = new CaseInsensitiveMap(); + answer.put("Enabled", boolean.class); + answer.put("FailureThreshold", int.class); + answer.put("Interval", long.class); + answer.put("Parent", java.lang.String.class); + return answer; + } + + @Override + public Object getOptionValue(Object obj, String name, boolean ignoreCase) { + org.apache.camel.main.HealthCheckConfigurationProperties target = (org.apache.camel.main.HealthCheckConfigurationProperties) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "enabled": + case "Enabled": return target.isEnabled(); + case "failurethreshold": + case "FailureThreshold": return target.getFailureThreshold(); + case "interval": + case "Interval": return target.getInterval(); + case "parent": + case "Parent": return target.getParent(); + default: return null; + } + } +} + diff --git a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json index 77f7c2c..6e11290 100644 --- a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json +++ b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json @@ -21,16 +21,16 @@ { "name": "camel.main.beanIntrospectionExtendedStatistics", "description": "Sets whether bean introspection uses extended statistics. The default is false.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean" }, { "name": "camel.main.beanIntrospectionLoggingLevel", "description": "Sets the logging level used by bean introspection, logging activity of its usage. The default is TRACE.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "object", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "ERROR", "WARN", "INFO", "DEBUG", "TRACE", "OFF" ] }, { "name": "camel.main.caseInsensitiveHeaders", "description": "Whether to use case sensitive or insensitive headers. Important: When using case sensitive (this is set to false). Then the map is case sensitive which means headers such as content-type and Content-Type are two different keys which can be a problem for some protocols such as HTTP based, which rely on case insensitive headers. However case sensitive implementations can yield faster performance. Therefore use case sensitiv [...] - { "name": "camel.main.config", "description": null, "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "object", "javaType": "java.util.Map", "defaultValue": "new HashMap<>()" }, + { "name": "camel.main.config", "description": "Set additional HealthConfigurationProperties for fine grained configuration of health checks.", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "object", "javaType": "java.util.Map", "defaultValue": "new HashMap<>()" }, { "name": "camel.main.configurationClasses", "description": "Sets classes names that will be used to configure the camel context as example by providing custom beans through org.apache.camel.BindToRegistry annotation.", "sourceType": "org.apache.camel.main.MainConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.main.configurations", "description": "Sets the configuration objects used to configure the camel context.", "sourceType": "org.apache.camel.main.MainConfigurationProperties", "type": "object", "javaType": "java.util.List", "defaultValue": "new ArrayList<>()" }, { "name": "camel.main.consumerTemplateCacheSize", "description": "Consumer template endpoints cache size.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 1000 }, - { "name": "camel.main.contextEnabled", "description": null, "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean" }, + { "name": "camel.main.contextEnabled", "description": "Whether context health check is enabled Is default enabled", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean" }, { "name": "camel.main.durationHitExitCode", "description": "Sets the exit code for the application if duration was hit", "sourceType": "org.apache.camel.main.MainConfigurationProperties", "type": "integer", "javaType": "int" }, { "name": "camel.main.durationMaxIdleSeconds", "description": "To specify for how long time in seconds Camel can be idle before automatic terminating the JVM. You can use this to run Camel for a short while.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", "javaType": "int" }, { "name": "camel.main.durationMaxMessages", "description": "To specify how many messages to process by Camel before automatic terminating the JVM. You can use this to run Camel for a short while.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", "javaType": "int" }, { "name": "camel.main.durationMaxSeconds", "description": "To specify for how long time in seconds to keep running the JVM before automatic terminating the JVM. You can use this to run Camel for a short while.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", "javaType": "int" }, - { "name": "camel.main.enabled", "description": null, "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean" }, + { "name": "camel.main.enabled", "description": "Whether health check is enabled globally", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean" }, { "name": "camel.main.endpointBasicPropertyBinding", "description": "Whether the endpoint should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities. The default value is false.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean" }, { "name": "camel.main.endpointBridgeErrorHandler", "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN\/ERROR level and ignored. The default va [...] { "name": "camel.main.endpointLazyStartProducer", "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first mes [...] @@ -52,7 +52,7 @@ { "name": "camel.main.name", "description": "Sets the name of the CamelContext.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.main.packageScanRouteBuilders", "description": "Sets package names for scanning for org.apache.camel.builder.RouteBuilder classes as candidates to be included. If you are using Spring Boot then its instead recommended to use Spring Boots component scanning and annotate your route builder classes with Component. In other words only use this for Camel Main in standalone mode.", "sourceType": "org.apache.camel.main.MainConfigurationProperties", "type": "string", "javaTy [...] { "name": "camel.main.producerTemplateCacheSize", "description": "Producer template endpoints cache size.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 1000 }, - { "name": "camel.main.registryEnabled", "description": null, "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean" }, + { "name": "camel.main.registryEnabled", "description": "Whether registry health check is enabled Is default enabled", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean" }, { "name": "camel.main.routeControllerBackOffDelay", "description": "Backoff delay in millis when restarting a route that failed to startup.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", "javaType": "long" }, { "name": "camel.main.routeControllerBackOffMaxAttempts", "description": "Backoff maximum number of attempts to restart a route that failed to startup. When this threshold has been exceeded then the controller will give up attempting to restart the route, and the route will remain as stopped.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", "javaType": "long" }, { "name": "camel.main.routeControllerBackOffMaxDelay", "description": "Backoff maximum delay in millis when restarting a route that failed to startup.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", "javaType": "long" }, @@ -70,7 +70,7 @@ { "name": "camel.main.routesBuilderClasses", "description": "Sets classes names that implement RoutesBuilder .", "sourceType": "org.apache.camel.main.MainConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.main.routesBuilders", "description": "Sets the RoutesBuilder instances.", "sourceType": "org.apache.camel.main.MainConfigurationProperties", "type": "object", "javaType": "java.util.List", "defaultValue": "new ArrayList<>()" }, { "name": "camel.main.routesCollectorEnabled", "description": "Whether the routes collector is enabled or not. When enabled Camel will auto-discover routes (RouteBuilder instances from the registry and also load additional XML routes from the file system. The routes collector is default enabled.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true }, - { "name": "camel.main.routesEnabled", "description": null, "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean" }, + { "name": "camel.main.routesEnabled", "description": "Whether routes health check is enabled Is default enabled", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean" }, { "name": "camel.main.shutdownLogInflightExchangesOnTimeout", "description": "Sets whether to log information about the inflight Exchanges which are still running during a shutdown which didn't complete without the given timeout. This requires to enable the option inflightRepositoryBrowseEnabled.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true }, { "name": "camel.main.shutdownNowOnTimeout", "description": "Sets whether to force shutdown of all consumers when a timeout occurred and thus not all consumers was shutdown within that period. You should have good reasons to set this option to false as it means that the routes keep running and is halted abruptly when CamelContext has been shutdown.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true }, { "name": "camel.main.shutdownRoutesInReverseOrder", "description": "Sets whether routes should be shutdown in reverse or the same order as they where started.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true }, diff --git a/core/camel-main/src/generated/resources/META-INF/services/org/apache/camel/configurer/HealthCheckConfigurationProperties b/core/camel-main/src/generated/resources/META-INF/services/org/apache/camel/configurer/HealthCheckConfigurationProperties new file mode 100644 index 0000000..5a563d7 --- /dev/null +++ b/core/camel-main/src/generated/resources/META-INF/services/org/apache/camel/configurer/HealthCheckConfigurationProperties @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.main.HealthCheckConfigurationPropertiesConfigurer 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 7a290f1..1a1b2e8 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 @@ -23,7 +23,6 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -664,7 +663,7 @@ public abstract class BaseMainSupport extends BaseService { // configure the common/default options DefaultConfigurationConfigurer.configure(camelContext, config); // lookup and configure SPI beans - DefaultConfigurationConfigurer.afterPropertiesSet(camelContext); + DefaultConfigurationConfigurer.afterConfigure(camelContext); // now configure context/hystrix/resilience4j/rest with additional properties Properties prop = camelContext.getPropertiesComponent().loadProperties(name -> name.startsWith("camel.")); @@ -801,10 +800,7 @@ public abstract class BaseMainSupport extends BaseService { } if (!healthProperties.isEmpty()) { LOG.debug("Auto-configuring HealthCheck from loaded properties: {}", healthProperties.size()); - HealthConfigurationProperties health = mainConfigurationProperties.health(); - setPropertiesOnTarget(camelContext, health, healthProperties, "camel.health.", - mainConfigurationProperties.isAutoConfigurationFailFast(), true, autoConfiguredProperties); - // TODO: setup health check via HealthConfigurationProperties + setHealthCheckProperties(camelContext, healthProperties, mainConfigurationProperties.isAutoConfigurationFailFast(), autoConfiguredProperties); } // log which options was not set @@ -855,6 +851,9 @@ public abstract class BaseMainSupport extends BaseService { LOG.warn("Property not auto-configured: camel.health{}={}", k, v); }); } + + // and call after all properties are set + DefaultConfigurationConfigurer.afterPropertiesSet(camelContext); } private void setThreadPoolProfileProperties(CamelContext camelContext, Map<String, Object> threadPoolProperties, @@ -935,9 +934,8 @@ public abstract class BaseMainSupport extends BaseService { } } - @Deprecated private void setHealthCheckProperties(CamelContext camelContext, Map<String, Object> healthCheckProperties, - boolean failIfNotSet, Map<String, String> autoConfiguredProperties) { + boolean failIfNotSet, Map<String, String> autoConfiguredProperties) throws Exception { HealthCheckRegistry hcr = camelContext.getExtension(HealthCheckRegistry.class); if (hcr == null) { @@ -945,162 +943,87 @@ public abstract class BaseMainSupport extends BaseService { return; } - // grab global option for enabled or disabled - String global = (String) healthCheckProperties.remove(".enabled"); - if (global != null) { - hcr.setEnabled(CamelContextHelper.parseBoolean(camelContext, global)); - autoConfiguredProperties.put("camel.health.enabled", global); - } + HealthConfigurationProperties health = mainConfigurationProperties.health(); - // common health checks to make them easy to turn on|off - String contextEnabled = (String) healthCheckProperties.remove(".context.enabled"); - if (contextEnabled != null) { - autoConfiguredProperties.put("camel.health.context.enabled", contextEnabled); - } - String routesEnabled = (String) healthCheckProperties.remove(".routes.enabled"); - if (routesEnabled != null) { - autoConfiguredProperties.put("camel.health.routes.enabled", routesEnabled); + // extract all config to know their parent ids so we can set the values afterwards + Map<String, Object> hcConfig = PropertiesHelper.extractProperties(healthCheckProperties, "config", false); + Map<String, HealthCheckConfigurationProperties> hcConfigs = new HashMap<>(); + // build set of configuration objects + for (Map.Entry<String, Object> entry : hcConfig.entrySet()) { + String parent = StringHelper.between(entry.getKey(), "[", "]"); + if (parent != null) { + HealthCheckConfigurationProperties hcp = hcConfigs.get(parent); + if (hcp == null) { + hcp = new HealthCheckConfigurationProperties(); + hcConfigs.put(parent, hcp); + } + } } - String registryEnabled = (String) healthCheckProperties.remove(".registry.enabled"); - if (registryEnabled != null) { - autoConfiguredProperties.put("camel.health.registry.enabled", registryEnabled); + if (health.getConfig() != null) { + health.getConfig().putAll(hcConfigs); + } else { + health.setConfig(hcConfigs); } - Map<String, Map<String, String>> checks = new LinkedHashMap<>(); - // the id of the health-check is in the key [xx] - healthCheckProperties.forEach((k, v) -> { - String id = StringHelper.between(k, "[", "]."); - if (id == null) { - throw new IllegalArgumentException("Invalid syntax for key: camel.health" + k + " should be: camel.health[id]"); - } - String key = StringHelper.after(k, "]."); - String value = v.toString(); - if (key == null) { - throw new PropertyBindingException("HealthCheckConfiguration", k, value); - } - Map<String, String> map = checks.computeIfAbsent(id, o -> new HashMap<>()); - map.put(optionKey(key), value); - -// if (failIfNotSet && !VALID_HEALTH_KEYS.contains(key)) { -// throw new PropertyBindingException("HealthCheckConfiguration", key, value); -// } - - autoConfiguredProperties.put("camel.health" + k, value); - }); - // clear as we have validated all parameters - healthCheckProperties.clear(); + setPropertiesOnTarget(camelContext, health, healthCheckProperties, "camel.health.", + mainConfigurationProperties.isAutoConfigurationFailFast(), true, autoConfiguredProperties); + if (health.getEnabled() != null) { + hcr.setEnabled(health.getEnabled()); + } // context is enabled by default - if (hcr.isEnabled() && (!checks.containsKey("context") || contextEnabled != null)) { + if (hcr.isEnabled() && (!health.getConfig().containsKey("context") || health.getContextEnabled() != null)) { HealthCheck hc = (HealthCheck) hcr.resolveById("context"); if (hc != null) { - if (contextEnabled != null) { - hc.getConfiguration().setEnabled(CamelContextHelper.parseBoolean(camelContext, contextEnabled)); + if (health.getContextEnabled() != null) { + hc.getConfiguration().setEnabled(health.getContextEnabled()); } hcr.register(hc); } } // routes is enabled by default - if (hcr.isEnabled() && (!checks.containsKey("routes") || routesEnabled != null)) { + if (hcr.isEnabled() && (!health.getConfig().containsKey("routes") || health.getRoutesEnabled() != null)) { HealthCheckRepository hc = hcr.getRepository("routes").orElse((HealthCheckRepository) hcr.resolveById("routes")); if (hc != null) { - if (routesEnabled != null) { - hc.setEnabled(CamelContextHelper.parseBoolean(camelContext, routesEnabled)); + if (health.getRoutesEnabled() != null) { + hc.setEnabled(health.getRoutesEnabled()); } hcr.register(hc); } } // registry is enabled by default - if (hcr.isEnabled() && (!checks.containsKey("registry") || registryEnabled != null)) { + if (hcr.isEnabled() && (!health.getConfig().containsKey("registry") || health.getRegistryEnabled() != null)) { hcr.getRepository("registry").ifPresent(h -> { - if (registryEnabled != null) { - h.setEnabled(CamelContextHelper.parseBoolean(camelContext, registryEnabled)); + if (health.getRegistryEnabled() != null) { + h.setEnabled(health.getRegistryEnabled()); } }); } - // extract all keys that are for sub configuration (such as fine grained on routes) - Map<String, Map<String, String>> subConfig = new LinkedHashMap<>(); - Iterator<String> it = checks.keySet().iterator(); - while (it.hasNext()) { - String key = it.next(); - // the key have their starting [ and ] removed, so we look for sub keys via [id][id2].key - if (key.contains("][")) { - String newKey = key.replace("][", ":"); - subConfig.put(newKey, checks.get(key)); - it.remove(); - } - } - // configure health checks configurations - for (String id : checks.keySet()) { - Map<String, String> map = checks.get(id); - String enabled = map.remove("enabled"); - String interval = map.remove("interval"); - String failureThreshold = map.remove("failureThreshold"); - - HealthCheckConfiguration hcc = new HealthCheckConfiguration(); - if (enabled != null) { - hcc.setEnabled(CamelContextHelper.parseBoolean(camelContext, enabled)); - } - if (interval != null) { - hcc.setInterval(CamelContextHelper.parseDuration(camelContext, interval).toMillis()); - } - if (failureThreshold != null) { - hcc.setFailureThreshold(CamelContextHelper.parseInt(camelContext, failureThreshold)); - } - + for (String id : health.getConfig().keySet()) { + HealthCheckConfiguration hcc = health.getConfig().get(id); + String parent = hcc.getParent(); // lookup health check by id - Object hc = hcr.getCheck(id).orElse(null); + Object hc = hcr.getCheck(parent).orElse(null); if (hc == null) { - hc = hcr.resolveById(id); + hc = hcr.resolveById(parent); if (hc == null) { - LOG.warn("Cannot resolve HealthCheck with id: " + id + " from classpath."); + LOG.warn("Cannot resolve HealthCheck with id: " + parent + " from classpath."); continue; } hcr.register(hc); if (hc instanceof HealthCheck) { + ((HealthCheck) hc).getConfiguration().setParent(hcc.getParent()); ((HealthCheck) hc).getConfiguration().setEnabled(hcc.isEnabled()); ((HealthCheck) hc).getConfiguration().setFailureThreshold(hcc.getFailureThreshold()); ((HealthCheck) hc).getConfiguration().setInterval(hcc.getInterval()); } else if (hc instanceof HealthCheckRepository) { ((HealthCheckRepository) hc).setEnabled(hcc.isEnabled()); + ((HealthCheckRepository) hc).addConfiguration(id, hcc); } } } - - // apply sub configuration for health check repositories - - // for example you can specify for all - // camel.health[routes][*].interval = 10s - // - // ... or per id - // - // camel.health[routes][timer].enabled = true - // camel.health[routes][timer].interval = 10s - // camel.health[routes][timer].failure-threshold = 5 - subConfig.forEach((k, v) -> { - String key = StringHelper.after(k, ":"); - Map configs = v; - String enabled = (String) configs.remove("enabled"); - String interval = (String) configs.remove("interval"); - String failureThreshold = (String) configs.remove("failureThreshold"); - HealthCheckConfiguration hcc = new HealthCheckConfiguration(); - if (enabled != null) { - hcc.setEnabled(CamelContextHelper.parseBoolean(camelContext, enabled)); - } - if (interval != null) { - hcc.setInterval(CamelContextHelper.parseDuration(camelContext, interval).toMillis()); - } - if (failureThreshold != null) { - hcc.setFailureThreshold(CamelContextHelper.parseInt(camelContext, failureThreshold)); - } - String id = StringHelper.before(k, ":"); - Object obj = hcr.resolveById(id); - if (obj instanceof HealthCheckRepository) { - ((HealthCheckRepository) obj).addConfiguration(key, hcc); - } - }); } private void bindBeansToRegistry(CamelContext camelContext, Map<String, Object> properties, diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java index 69a64d5..7cb17af 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java @@ -221,7 +221,7 @@ public final class DefaultConfigurationConfigurer { * Similar code in camel-core-xml module in class org.apache.camel.core.xml.AbstractCamelContextFactoryBean * or in camel-spring-boot module in class org.apache.camel.spring.boot.CamelAutoConfiguration. */ - public static void afterPropertiesSet(final CamelContext camelContext) throws Exception { + public static void afterConfigure(final CamelContext camelContext) throws Exception { final Registry registry = camelContext.getRegistry(); final ManagementStrategy managementStrategy = camelContext.getManagementStrategy(); final ExtendedCamelContext ecc = camelContext.adapt(ExtendedCamelContext.class); @@ -390,6 +390,10 @@ public final class DefaultConfigurationConfigurer { initThreadPoolProfiles(registry, camelContext); } + public static void afterPropertiesSet(final CamelContext camelContext) throws Exception { + // additional configuration + } + private static <T> T getSingleBeanOfType(Registry registry, Class<T> type) { Map<String, T> beans = registry.findByTypeWithName(type); if (beans.size() == 1) { diff --git a/core/camel-main/src/main/java/org/apache/camel/main/HealthCheckConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/HealthCheckConfigurationProperties.java new file mode 100644 index 0000000..1488223 --- /dev/null +++ b/core/camel-main/src/main/java/org/apache/camel/main/HealthCheckConfigurationProperties.java @@ -0,0 +1,9 @@ +package org.apache.camel.main; + +import org.apache.camel.health.HealthCheckConfiguration; +import org.apache.camel.spi.Configurer; + +@Configurer +public class HealthCheckConfigurationProperties extends HealthCheckConfiguration { + +} 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 0d59b30..5cba654 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 @@ -33,7 +33,7 @@ public class HealthConfigurationProperties { private Boolean contextEnabled; private Boolean routesEnabled; private Boolean registryEnabled; - private Map<String, HealthConfiguration> config = new HashMap<>(); + private Map<String, HealthCheckConfigurationProperties> config = new HashMap<>(); public HealthConfigurationProperties(MainConfigurationProperties parent) { this.parent = parent; @@ -47,6 +47,9 @@ public class HealthConfigurationProperties { return enabled; } + /** + * Whether health check is enabled globally + */ public void setEnabled(Boolean enabled) { this.enabled = enabled; } @@ -55,6 +58,11 @@ public class HealthConfigurationProperties { return contextEnabled; } + /** + * Whether context health check is enabled + * + * Is default enabled + */ public void setContextEnabled(Boolean contextEnabled) { this.contextEnabled = contextEnabled; } @@ -63,6 +71,11 @@ public class HealthConfigurationProperties { return routesEnabled; } + /** + * Whether routes health check is enabled + * + * Is default enabled + */ public void setRoutesEnabled(Boolean routesEnabled) { this.routesEnabled = routesEnabled; } @@ -71,49 +84,70 @@ public class HealthConfigurationProperties { return registryEnabled; } + /** + * Whether registry health check is enabled + * + * Is default enabled + */ public void setRegistryEnabled(Boolean registryEnabled) { this.registryEnabled = registryEnabled; } - public Map<String, HealthConfiguration> getConfig() { + public Map<String, HealthCheckConfigurationProperties> getConfig() { return config; } - public void setConfig(Map<String, HealthConfiguration> config) { + /** + * Set additional {@link HealthConfigurationProperties} for fine grained configuration of health checks. + */ + public void setConfig(Map<String, HealthCheckConfigurationProperties> config) { this.config = config; } - // TODO: Fluent builder - - @Configurer - public static class HealthConfiguration { - - private Boolean enabled; - private Long interval; - private Integer failureThreshold; - - public Boolean getEnabled() { - return enabled; - } - - public void setEnabled(Boolean enabled) { - this.enabled = enabled; - } + /** + * Whether health check is enabled globally + */ + public HealthConfigurationProperties withEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } - public Long getInterval() { - return interval; - } + /** + * Whether context health check is enabled + * + * Is default enabled + */ + public HealthConfigurationProperties withContextEnabled(boolean contextEnabled) { + this.contextEnabled = contextEnabled; + return this; + } - public void setInterval(Long interval) { - this.interval = interval; - } + /** + * Whether routes health check is enabled + * + * Is default enabled + */ + public HealthConfigurationProperties withRoutesEnabled(boolean routesEnabled) { + this.routesEnabled = routesEnabled; + return this; + } - public Integer getFailureThreshold() { - return failureThreshold; - } + /** + * Whether registry health check is enabled + * + * Is default enabled + */ + public HealthConfigurationProperties withRegistryEnabled(boolean registryEnabled) { + this.registryEnabled = registryEnabled; + return this; + } - public void setFailureThreshold(Integer failureThreshold) { - this.failureThreshold = failureThreshold; - } + /** + * Additional {@link HealthConfigurationProperties} for fine grained configuration of health checks. + */ + public HealthConfigurationProperties addConfig(String id, HealthCheckConfigurationProperties config) { + this.config.put(id, config); + return this; } + }