Last active
April 13, 2018 06:29
-
-
Save atorstling/d2669ba477924adac88d3caff6a36e8d to your computer and use it in GitHub Desktop.
A Vert.x 3 launcher which overrides root level JSON config properties with values from system properties and/or environment variables
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import io.vertx.core.DeploymentOptions; | |
import io.vertx.core.Launcher; | |
import io.vertx.core.json.JsonObject; | |
import java.io.InputStream; | |
import java.lang.reflect.InvocationTargetException; | |
import java.util.Map; | |
import java.util.Scanner; | |
/** | |
* A launcher which enables overriding properties in the deployment config | |
* by using system properties and environment variables. | |
* | |
* The launcher also looks for a default config in the classpath at /defaults-conf.json. | |
* If you define sensible defaults in this file you get a nice setup where you aren't required | |
* to send in any conf, but can if you want to. And you are able to override properties. | |
**/ | |
public class PropertiesLauncher extends Launcher { | |
public static void main(String[] args) { | |
new PropertiesLauncher().dispatch(args); | |
} | |
@Override | |
public void beforeDeployingVerticle(DeploymentOptions deploymentOptions) { | |
JsonObject inputConf = deploymentOptions.getConfig(); | |
final JsonObject conf = inputConf == null ? readDefaultsConf() : inputConf; | |
if (conf != null) { | |
JsonObject moddedConf = conf.copy(); | |
for (Map.Entry<String, Object> e : moddedConf) { | |
String key = e.getKey(); | |
Prop prop = getProp(key); | |
if (prop != null) { | |
Class<?> type = e.getValue().getClass(); | |
Object value = convertType(type, prop.value); | |
System.out.println(String.format( | |
"Overriding %s=%s of type %s with %s %s=%s. New converted value is '%s'", | |
key, e.getValue(), type.getName(), prop.source, prop.key, prop.value, value) | |
); | |
moddedConf.put(key, value); | |
} | |
} | |
deploymentOptions.setConfig(moddedConf); | |
} | |
} | |
private JsonObject readDefaultsConf() { | |
InputStream defaultsConf = getClass().getResourceAsStream("/defaults-conf.json"); | |
return defaultsConf == null ? null: new JsonObject(toStr(defaultsConf)); | |
} | |
private String toStr(InputStream is) { | |
// http://stackoverflow.com/a/5445161/83741 | |
Scanner s = new Scanner(is).useDelimiter("\\A"); | |
return s.hasNext() ? s.next() : ""; | |
} | |
private Object convertType(Class<?> type, String value) { | |
// http://stackoverflow.com/a/13569408/83741 | |
try { | |
return type.getConstructor( String.class ).newInstance(value); | |
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { | |
throw new IllegalStateException(String.format("Could not convert value %s into type %s, tried finding a " + | |
"String constructor", value, type), e); | |
} | |
} | |
static class Prop { | |
String source; | |
String key; | |
String value; | |
public Prop(String source, String key, String value) { | |
this.source = source; | |
this.key = key; | |
this.value = value; | |
} | |
} | |
static Prop getProp(final String name) { | |
String sysPropValue = System.getProperty(name); | |
if (sysPropValue != null) { | |
return new Prop("system property", name, sysPropValue); | |
} | |
String envKey = name.toUpperCase().replaceAll("\\.", "_"); | |
String envValue = System.getenv(envKey); | |
if (envValue != null) { | |
return new Prop("environment variable", envKey, envValue); | |
} | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment