Java configuration library that uses JSON, YAML, or Javascript configuration files.
This project is maintained by advantageous
Java configuration library similar in concept to TypeSafe config, but uses full JavaScript, YAML or JSON for configuration.
Uses JavaScript/JSON/YAML as config for Java.
You can use full JavaScript for configuration as long as you define a
variable called config
that results in a JavaScript object which
equates to a Java map.
Konf is in the public maven repo.
<dependency>
<groupId>io.advantageous.konf</groupId>
<artifactId>konf</artifactId>
<version>1.3.0.RELEASE</version>
</dependency>
compile 'io.advantageous.konf:konf:1.3.0.RELEASE'
libraryDependencies += "io.advantageous.konf" % "konf" % "1.3.0.RELEASE"
[io.advantageous.konf/konf "1.3.0.RELEASE"]
Here is an example config for JavaScript.
Konf expects the config
variable to be set to a JavaScript object with
properties.
var config = {
myUri: uri("http://host:9000/path?foo=bar"),
someKey: {
nestedKey: 234,
other: "this text"
}
};
You can define you own config DSL for your environment. We have a full example that shows you how to create a custom config DSL for your internal projects. The example uses Mesosphere and Docker PORT look ups and it is from a real project.
var config = {
platform: {
statsd: "udp://" + getDockerHost() + ":8125",
servicePort: mesosPortAt(0, 8080),
adminPort: mesosPortAt(1, 9090),
...
See the real world for example that uses Konf to find ports under Mesosphere (running in stating or prod) or under Docker (running on a local developers box).
The Java interface for Konf is Config.
You can get a sub Config from Config (getConfig(path)
).
The path
is always in dot notation (this.that.foo.bar
).
You can also use:
hasPath(path)
getInt(path)
getLong(path)
getDouble(path)
getBoolean(path)
can be true, false, "yes", "no", "on", "off", yes, no, off, ongetString(path)
getStringList(path)
gets a list of stringsgetConfig(path)
gets a sub-config.getMap(path)
gets a map which is a sub-config.getConfigList(path)
gets a list of configs at the location specified.getIntList(path)
getLongList(path)
getDoubleList(path)
getBooleanList(path)
getDuration(path)
gets java.time.Duration
useful for timeoutsgetDurationList(path)
gets duration listgetUripath)
gets java.net.URI
useful for connecting to downstream servicesgetUriList(path)
useful for connecting to downstream servicesgetMap
works with JavaScript objects. getStringList
and getConfigList
works
with JavaScript array of string and a JavaScript array of JavaScript objects.
Not you get an exception if the path
requested is not found.
Use hasPath(path)
if you think the config path might be missing.
Here is the full interface.
public interface Config {
/** Get string at location. */
String getString(String path);
/** Checks to see if config has the path specified. */
boolean hasPath(String path);
/** Get int at location. */
int getInt(String path);
/** Get float at location. */
float getFloat(String path);
/** Get double at location. */
double getDouble(String path);
/** Get long at location. */
long getLong(String path);
/** Get list of strings at location. */
List<String> getStringList(String path);
/** Get map at location. */
Map<String, Object> getMap(String path);
/** Get a sub-config at location. */
Config getConfig(String path);
/** Get list of sub-configs at location. */
List<Config> getConfigList(String path);
/** Get a single POJO out of config at path. */
<T> T get(String path, Class<T> type);
/** Get a list of POJOs. */
<T> List<T> getList(String path, Class<T> componentType);
/** Get duration. Good for timeouts */
Duration getDuration(String path);
/** Get duration list. */
List<Duration> getDurationList(String path);
/** Get int list. */
List<Integer> getIntegerList(String path);
...
}
The getX
methods work like you would expect. Given this config file.
sysProp(propName)
to read a sysProp as in fooSize : sysProp("my.foo.size")
sysPropOrDefault(propName, defaultValue)
to read a sysProp or a defaultisWindowsOS()
, isMacOS()
, isUnix()
, isLinux()
, isSolaris()
env()
as in fooSize : env('MY_FOO_SIZE')
or even fooSize : sysPropOrDefault("my.foo.size", env('MY_FOO_SIZE'))
uri()
which creates a java.net.URI
as in fooURI : uri ("http://localhost:8080/")
java.time.Duration
is imported as duration
java.lang.System
is imported as system
seconds(units)
, minutes(units)
, hours(units)
, days(units)
, millis(units)
and milliseconds(units
) define a Duration
which is useful for configuring timeouts and interval jobsyes
, no
, on
, off
for boolean configvar config = {
myUri: uri("http://host:9000/path?foo=bar"),
someKey: {
nestedKey: 234,
other: "this text"
},
int1: 1,
float1: 1.0,
double1: 1.0,
long1: 1,
string1: "rick",
stringList: ['Foo', 'Bar'],
configInner: {
int2: 2,
float2: 2.0
},
uri: uri("http://localhost:8080/foo"),
myClass: "java.lang.Object",
myURI: "http://localhost:8080/foo",
employee: {"id": 123, "name": "Geoff"},
employees: [
{id: 123, "name": "Geoff"},
{id: 456, "name": "Rick"},
{id: 789, 'name': "Paul"}
]
};
We can do the following operations.
First we load the config.
private Config config;
@Before
public void setUp() throws Exception {
config = ConfigLoader.load("test-config.js");
}
Note that ConfigLoader.load
takes a variable length string array.
By default a resource String can contain a valid URI, which
can have the scheme classpath
, file
, or http
. If you do not specify
a scheme than the path is assumed to be a classpath resource.
config = ConfigLoader.load(
"/io/mycompany/foo-classpath.js",
"classpath:test-config.js",
"classpath://foo.js",
"classpath:/bar.js",
"file://opt/app/config.js",
"file:///opt/app/config2.js",
"file:/opt/app/config.js",
"http://my.internal.server:9090/foo.js"
);
Then we show reading basic types with the config
object using getX
.
@Test
public void testSimple() throws Exception {
//getInt
assertEquals(1, config.getInt("int1"));
//getStringList
assertEquals(asList("Foo", "Bar"),
config.getStringList("stringList"));
//getString
assertEquals("rick", config.getString("string1"));
//getDouble
assertEquals(1.0, config.getDouble("double1"), 0.001);
//getLong
assertEquals(1L, config.getLong("long1"));
//getFloat
assertEquals(1.0f, config.getFloat("float1"), 0.001);
//Basic JDK value types are supported like class.
assertEquals(Object.class, config.get("myClass", Class.class));
//Basic JDK value types are supported like URI.
assertEquals(URI.create("http://localhost:8080/foo"),
config.get("myURI", URI.class));
assertEquals(URI.create("http://localhost:8080/foo"),
config.get("uri", URI.class));
}
You can work with nested properties as well.
@Test
public void testGetConfig() throws Exception {
//Read nested config.
final Config configInner = config.getConfig("configInner");
assertEquals(2, configInner.getInt("int2"));
assertEquals(2.0f, configInner.getFloat("float2"), 0.001);
}
@Test
public void testGetMap() throws Exception {
//Read nested config as a Java map.
final Map<String, Object> map = config.getMap("configInner");
assertEquals(2, (int) map.get("int2"));
assertEquals(2.0f, (double) map.get("float2"), 0.001);
}
You can read deeply nested config items as well by specifying the property path using dot notation.
@Test
public void testSimplePath() throws Exception {
assertTrue(config.hasPath("configInner.int2"));
assertFalse(config.hasPath("configInner.foo.bar"));
assertEquals(2, config.getInt("configInner.int2"));
assertEquals(2.0f, config.getFloat("configInner.float2"), 0.001);
}
You can also read POJOs directly out of the config file.
@Test
public void testReadClass() throws Exception {
final Employee employee = config.get("employee", Employee.class);
assertEquals("Geoff", employee.name);
assertEquals("123", employee.id);
}
You can read a list of POJOs at once.
@Test
public void testReadListOfClass() throws Exception {
final List<Employee> employees = config.getList("employees", Employee.class);
assertEquals("Geoff", employees.get(0).name);
assertEquals("123", employees.get(0).id);
}
You can also read a list of config objects out of the config as well.
final List<Config> employees = config.getConfigList("employees");
assertEquals("Geoff", employees.get(0).getString("name"));
assertEquals("123", employees.get(0).getString("id"));
First include a YAML to object parser like YAML Beans or a library like this.
name: Nathan Sweet
age: 28
address: 4011 16th Ave S
phone numbers:
- name: Home
number: 206-555-5138
- name: Work
number: 425-555-2306
//Use YamlReader to load YAML file.
YamlReader reader = new YamlReader(new FileReader("contact.yml"));
//Convert object read from YAML into Konf config
Config config = ConfigLoader.loadFromObject(reader.read());
//Now you have strongly typed access to fields
String address = config.getString("address");
You can also read Pojos from anywhere in the YAML file as well as sub configs.
See Boon JSON parser project, and Boon in five minutes
ObjectMapper mapper = JsonFactory.create();
/* Convert object read from YAML into Konf config.
'src' can be File, InputStream, Reader, String. */
Config config = ConfigLoader.loadFromObject(mapper.fromJson(src));
//Now you have strongly typed access to fields
String address = config.getString("address");
Boon supports LAX JSON (Json with comments, and you do not need to quote the field).
getDuration(path)
get a durationgetDurationList(path)
get a duration listKonf supports "10 seconds" style config for duration as well as having built-in functions and support for ISO-8601. See documentation for duration config for more details.
getIntList
reads list of intsgetLongList
reads list of longsgetDoubleList
reads list of doublesgetFloatList
reads list of floatsSee documentation list of number configuration for more details.
getMemorySize(path)
getMemorySizeList(path)
This means we support config like:
diskSpace : " 10 gigabytes",
diskVolumes : [" 10 gigabytes", "10GB", "10 gigabytes", 10]
We support the following size Strings.
If you like our configuration project, please try our Reactive Java project or our Actor based microservices lib.