A Vert.x 3 launcher which overrides root level JSON config properties with values from system properties and/or environment variables
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