Skip to content

Commit

Permalink
CAMEL-13683: camel-main - configuring properties report better error …
Browse files Browse the repository at this point in the history
…if missing JARs on classpathand other mistakes.
  • Loading branch information
davsclaus committed Jun 26, 2019
1 parent 7d11d5d commit ceb0253
Showing 1 changed file with 105 additions and 52 deletions.
157 changes: 105 additions & 52 deletions core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
Expand Up @@ -28,6 +28,7 @@
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -733,6 +734,7 @@ protected void postProcessCamelContext(CamelContext camelContext) throws Excepti


// need to eager allow to auto configure properties component // need to eager allow to auto configure properties component
if (mainConfigurationProperties.isAutoConfigurationEnabled()) { if (mainConfigurationProperties.isAutoConfigurationEnabled()) {
autoConfigurationFailFast(camelContext);
autoConfigurationPropertiesComponent(camelContext); autoConfigurationPropertiesComponent(camelContext);
autoConfigurationMainConfiguration(camelContext, mainConfigurationProperties); autoConfigurationMainConfiguration(camelContext, mainConfigurationProperties);
} }
Expand Down Expand Up @@ -765,6 +767,31 @@ protected void postProcessCamelContext(CamelContext camelContext) throws Excepti
} }
} }


protected void autoConfigurationFailFast(CamelContext camelContext) throws Exception {
// load properties
Properties prop = camelContext.getPropertiesComponent().loadProperties();
LOG.debug("Properties from Camel properties component:");
for (String key : prop.stringPropertyNames()) {
LOG.debug(" {}={}", key, prop.getProperty(key));
}

// load properties from ENV (override existing)
Properties propENV = loadEnvironmentVariablesAsProperties(new String[]{"camel.main."});
if (!propENV.isEmpty()) {
prop.putAll(propENV);
LOG.debug("Properties from OS environment variables:");
for (String key : propENV.stringPropertyNames()) {
LOG.debug(" {}={}", key, propENV.getProperty(key));
}
}

// special for fail-fast as we need to know this early before we set all the other options
Object failFast = propENV.remove("camel.main.autoconfigurationfailfast");
if (failFast != null) {
PropertyBindingSupport.bindMandatoryProperty(camelContext, mainConfigurationProperties, "autoConfigurationFailFast", failFast, true);
}
}

/** /**
* Configures CamelContext from the {@link MainConfigurationProperties} properties. * Configures CamelContext from the {@link MainConfigurationProperties} properties.
*/ */
Expand Down Expand Up @@ -864,73 +891,57 @@ protected void doConfigureCamelContextFromMainConfiguration(CamelContext camelCo
} }
setPropertiesOnTarget(camelContext, rest, restProperties, mainConfigurationProperties.isAutoConfigurationFailFast(), true); setPropertiesOnTarget(camelContext, rest, restProperties, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
} }

// TODO: Log which options was not set
} }


protected void autoConfigurationPropertiesComponent(CamelContext camelContext) throws Exception { protected void autoConfigurationPropertiesComponent(CamelContext camelContext) throws Exception {
// load properties // load properties
Properties prop = camelContext.getPropertiesComponent().loadProperties(); Properties prop = camelContext.getPropertiesComponent().loadProperties();
LOG.debug("Properties from Camel properties component:");
for (String key : prop.stringPropertyNames()) {
LOG.debug(" {}={}", key, prop.getProperty(key));
}


// load properties from ENV (override existing) // load properties from ENV (override existing)
Properties propENV = loadEnvironmentVariablesAsProperties(new String[]{"camel.component.properties."}); Properties propENV = loadEnvironmentVariablesAsProperties(new String[]{"camel.component.properties."});
if (!propENV.isEmpty()) { if (!propENV.isEmpty()) {
prop.putAll(propENV); prop.putAll(propENV);
LOG.debug("Properties from OS environment variables:");
for (String key : propENV.stringPropertyNames()) {
LOG.debug(" {}={}", key, propENV.getProperty(key));
}
} }


Map<Object, Map<String, Object>> properties = new LinkedHashMap<>(); Map<String, Object> properties = new LinkedHashMap<>();


for (String key : prop.stringPropertyNames()) { for (String key : prop.stringPropertyNames()) {
if (key.startsWith("camel.component.properties.")) { if (key.startsWith("camel.component.properties.")) {
Component component = camelContext.getPropertiesComponent();
int dot = key.indexOf(".", 26); int dot = key.indexOf(".", 26);
String option = dot == -1 ? "" : key.substring(dot + 1); String option = dot == -1 ? "" : key.substring(dot + 1);
String value = prop.getProperty(key, ""); String value = prop.getProperty(key, "");
validateOptionAndValue(key, option, value); validateOptionAndValue(key, option, value);
Map<String, Object> values = properties.getOrDefault(component, new LinkedHashMap<>()); properties.put(optionKey(option), value);
values.put(optionKey(option), value);
properties.put(component, values);
} }
} }


if (!properties.isEmpty()) { if (!properties.isEmpty()) {
long total = properties.values().stream().mapToLong(Map::size).sum(); LOG.info("Auto configuring properties component from loaded properties: {}", properties.size());
LOG.info("Auto configuring properties component from loaded properties: {}", total); setPropertiesOnTarget(camelContext, camelContext.getPropertiesComponent(), properties, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
} }


for (Object obj : properties.keySet()) { // log which options was not set
Map<String, Object> values = properties.get(obj); if (!properties.isEmpty()) {
setPropertiesOnTarget(camelContext, obj, values, mainConfigurationProperties.isAutoConfigurationFailFast(), true); properties.forEach((k, v) -> {
LOG.warn("Property not auto configured: camel.component.properties.{}={} on object: {}", k, v, camelContext.getPropertiesComponent());
});
} }
} }


protected void autoConfigurationMainConfiguration(CamelContext camelContext, MainConfigurationProperties config) throws Exception { protected void autoConfigurationMainConfiguration(CamelContext camelContext, MainConfigurationProperties config) throws Exception {
// load properties // load properties
Properties prop = camelContext.getPropertiesComponent().loadProperties(); Properties prop = camelContext.getPropertiesComponent().loadProperties();
LOG.debug("Properties from Camel properties component:");
for (String key : prop.stringPropertyNames()) {
LOG.debug(" {}={}", key, prop.getProperty(key));
}


// load properties from ENV (override existing) // load properties from ENV (override existing)
Properties propENV = loadEnvironmentVariablesAsProperties(new String[]{"camel.main."}); Properties propENV = loadEnvironmentVariablesAsProperties(new String[]{"camel.main."});
if (!propENV.isEmpty()) { if (!propENV.isEmpty()) {
prop.putAll(propENV); prop.putAll(propENV);
LOG.debug("Properties from OS environment variables:");
for (String key : propENV.stringPropertyNames()) {
LOG.debug(" {}={}", key, propENV.getProperty(key));
}
} }


Map<String, Object> properties = new LinkedHashMap<>(); Map<String, Object> properties = new LinkedHashMap<>();



for (String key : prop.stringPropertyNames()) { for (String key : prop.stringPropertyNames()) {
if (key.startsWith("camel.main.")) { if (key.startsWith("camel.main.")) {
// grab the value // grab the value
Expand All @@ -941,16 +952,17 @@ protected void autoConfigurationMainConfiguration(CamelContext camelContext, Mai
} }
} }


// special for fail-fast as we need to know this early before we set all the other options
Object failFast = properties.remove("autoconfigurationfailfast");
if (failFast != null) {
PropertyBindingSupport.bindMandatoryProperty(camelContext, config, "autoConfigurationFailFast", failFast, true);
}

if (!properties.isEmpty()) { if (!properties.isEmpty()) {
LOG.info("Auto configuring main from loaded properties: {}", properties.size()); LOG.info("Auto configuring main from loaded properties: {}", properties.size());
setPropertiesOnTarget(camelContext, config, properties, mainConfigurationProperties.isAutoConfigurationFailFast(), true); setPropertiesOnTarget(camelContext, config, properties, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
} }

// log which options was not set
if (!properties.isEmpty()) {
properties.forEach((k, v) -> {
LOG.warn("Property not auto configured: camel.main.{}={} on object: {}", k, v, config);
});
}
} }


protected void autoConfigurationFromProperties(CamelContext camelContext) throws Exception { protected void autoConfigurationFromProperties(CamelContext camelContext) throws Exception {
Expand Down Expand Up @@ -978,22 +990,14 @@ protected void autoConfigurationFromProperties(CamelContext camelContext) throws
// load properties from properties component (override existing) // load properties from properties component (override existing)
Properties propPC = camelContext.getPropertiesComponent().loadProperties(); Properties propPC = camelContext.getPropertiesComponent().loadProperties();
prop.putAll(propPC); prop.putAll(propPC);
LOG.debug("Properties from Camel properties component:");
for (String key : propPC.stringPropertyNames()) {
LOG.debug(" {}={}", key, propPC.getProperty(key));
}


// load properties from ENV (override existing) // load properties from ENV (override existing)
Properties propENV = loadEnvironmentVariablesAsProperties(new String[]{"camel.component.", "camel.dataformat.", "camel.language."}); Properties propENV = loadEnvironmentVariablesAsProperties(new String[]{"camel.component.", "camel.dataformat.", "camel.language."});
if (!propENV.isEmpty()) { if (!propENV.isEmpty()) {
prop.putAll(propENV); prop.putAll(propENV);
LOG.debug("Properties from OS environment variables:");
for (String key : propENV.stringPropertyNames()) {
LOG.debug(" {}={}", key, propENV.getProperty(key));
}
} }


Map<Object, Map<String, Object>> properties = new LinkedHashMap<>(); Map<PropertyOptionKey, Map<String, Object>> properties = new LinkedHashMap<>();


for (String key : prop.stringPropertyNames()) { for (String key : prop.stringPropertyNames()) {
if (key.startsWith("camel.component.")) { if (key.startsWith("camel.component.")) {
Expand All @@ -1012,10 +1016,11 @@ protected void autoConfigurationFromProperties(CamelContext camelContext) throws
String option = dot == -1 ? "" : key.substring(dot + 1); String option = dot == -1 ? "" : key.substring(dot + 1);
String value = prop.getProperty(key, ""); String value = prop.getProperty(key, "");
validateOptionAndValue(key, option, value); validateOptionAndValue(key, option, value);
Map<String, Object> values = properties.getOrDefault(component, new LinkedHashMap<>()); PropertyOptionKey pok = new PropertyOptionKey(key, component);
Map<String, Object> values = properties.getOrDefault(pok, new LinkedHashMap<>());
// we ignore case for property keys (so we should store them in canonical style // we ignore case for property keys (so we should store them in canonical style
values.put(optionKey(option), value); values.put(optionKey(option), value);
properties.put(component, values); properties.put(pok, values);
} }
if (key.startsWith("camel.dataformat.")) { if (key.startsWith("camel.dataformat.")) {
// grab name // grab name
Expand All @@ -1029,9 +1034,10 @@ protected void autoConfigurationFromProperties(CamelContext camelContext) throws
String option = dot == -1 ? "" : key.substring(dot + 1); String option = dot == -1 ? "" : key.substring(dot + 1);
String value = prop.getProperty(key, ""); String value = prop.getProperty(key, "");
validateOptionAndValue(key, option, value); validateOptionAndValue(key, option, value);
Map<String, Object> values = properties.getOrDefault(dataformat, new LinkedHashMap<>()); PropertyOptionKey pok = new PropertyOptionKey(key, dataformat);
Map<String, Object> values = properties.getOrDefault(pok, new LinkedHashMap<>());
values.put(optionKey(option), value); values.put(optionKey(option), value);
properties.put(dataformat, values); properties.put(pok, values);
} }
if (key.startsWith("camel.language.")) { if (key.startsWith("camel.language.")) {
// grab name // grab name
Expand All @@ -1047,9 +1053,10 @@ protected void autoConfigurationFromProperties(CamelContext camelContext) throws
String option = dot == -1 ? "" : key.substring(dot + 1); String option = dot == -1 ? "" : key.substring(dot + 1);
String value = prop.getProperty(key, ""); String value = prop.getProperty(key, "");
validateOptionAndValue(key, option, value); validateOptionAndValue(key, option, value);
Map<String, Object> values = properties.getOrDefault(language, new LinkedHashMap<>()); PropertyOptionKey pok = new PropertyOptionKey(key, language);
Map<String, Object> values = properties.getOrDefault(pok, new LinkedHashMap<>());
values.put(optionKey(option), value); values.put(optionKey(option), value);
properties.put(language, values); properties.put(pok, values);
} }
} }


Expand All @@ -1058,12 +1065,21 @@ protected void autoConfigurationFromProperties(CamelContext camelContext) throws
LOG.info("Auto configuring {} components/dataformat/languages from loaded properties: {}", properties.size(), total); LOG.info("Auto configuring {} components/dataformat/languages from loaded properties: {}", properties.size(), total);
} }


for (Object obj : properties.keySet()) { // TODO: Better error if setting some property fails
Map<String, Object> values = properties.get(obj); for (PropertyOptionKey pok : properties.keySet()) {
setPropertiesOnTarget(camelContext, obj, values, mainConfigurationProperties.isAutoConfigurationFailFast(), true); Map<String, Object> values = properties.get(pok);
setPropertiesOnTarget(camelContext, pok.getInstance(), values, mainConfigurationProperties.isAutoConfigurationFailFast(), true);
} }


// TODO: Log which options was not set // log which options was not set
if (!properties.isEmpty()) {
for (PropertyOptionKey pok : properties.keySet()) {
Map<String, Object> values = properties.get(pok);
values.forEach((k, v) -> {
LOG.warn("Property not auto configured: {}={} on object: {}", pok.getKey(), v, pok.getInstance());
});
}
}
} }


protected void autoConfigurationFromRegistry(CamelContext camelContext, boolean deepNesting) throws Exception { protected void autoConfigurationFromRegistry(CamelContext camelContext, boolean deepNesting) throws Exception {
Expand Down Expand Up @@ -1165,6 +1181,43 @@ private static boolean setPropertiesOnTarget(CamelContext context, Object target
return rc; return rc;
} }


private static class PropertyOptionKey {

private final String key;
private final Object instance;

private PropertyOptionKey(String key, Object instance) {
this.key = key;
this.instance = instance;
}

public String getKey() {
return key;
}

public Object getInstance() {
return instance;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
PropertyOptionKey that = (PropertyOptionKey) o;
return key.equals(that.key) &&
instance.equals(that.instance);
}

@Override
public int hashCode() {
return Objects.hash(key, instance);
}
}

public abstract class Option { public abstract class Option {
private String abbreviation; private String abbreviation;
private String fullName; private String fullName;
Expand Down

0 comments on commit ceb0253

Please sign in to comment.