AppConfigr is a small helper to manage local configuration files for applications. It is built on top of Jackson and its databind capabilities. It has the following key features:
- Provide access to configuration files in a dedicated configuration directory
- Support of environment variables and system properties in configuration files
- Support of different file formats (whatever is supported by Jackson databind)
- Support of properties in configuration files for internationalization purposes
- Support of updatable configuration data
Java 1.7 or higher is needed. AppConfigr additionally depends on Jackson for mapping the configuration files to Java objects and Guava which is used internally.
Create a simple configuration class.
public class MyAppConfig {
// define default values by just assign them on initialization.
private int myInt;
private int myString;
public int getMyInt() {return myInt;}
public String getMyString() {return myString;}
}
Create a file in the config folder ("path/to/config/files") with the name "my-app-config.conf" and the content
myInt: 12
myString: this is my configuration string
The default file format for the configuration files is yaml. It can be changed, see here
Create a new AppConfigr instance with the configuration directory as parameter.
import io.github.tommy1199.appconfigr.AppConfigr;
AppConfigr configr = AppConfigr.fromDirectory("path/to/config/files")
.build();
Now the configuration file can be loaded and used in the application. The following
MyAppConfig config = configr.getConfig(MyAppConfig.class);
System.out.println("The value of myInt is [" + config.getMyInt() + "]");
System.out.println("The value of myString is [" + config.getMyString() + "]");
will print:
The value of myInt is [12]
The value of myString is [this is my configuration string]
On top of the rich features already provided by jackson, it is possible to use variables in the configuration files. As default AppConfigr tries to resolve the variables by System Properties and then by Environment Variables in this order.
If we change the content of the configuration file in the Getting Started section to:
myInt: ${props.int}
myString: ${props.string}
and set the properties on application startup
java -Dprops.int=12 -Dprops.string="this is my configuration string" ...
we would get the same output.
The normal behaviour of AppConfigr is to use the configuration class name for looking up the file name. The rule is to use transform the class name to a lowercase hyphenated version with .conf suffix. An example can be seen below.
MyOwnConfiguration.class --> my-own-configuration.conf
If you want to specify an own file name, e.g. if you have several files with the same mapping, you can just use the overloaded method
MyAppConfig config = configr.getConfig(MyAppConfig.class, "my-custom-filename.conf");
If you want to change the way variables are resolved by AppConfigr, you can define an own Resolver and set it on the Builder. Defining an own resolver is pretty simple, just extend the class VariableResolver.
public class MyOwnResolver extends VariableResolver {
@Override
Result resolve(String variableName) {
// here resolve the variable
}
}
Then simply use it during building AppConfigr instance
AppConfigr.fromDirectory("path/to/config/files")
.withResolvingStrategy(new MyOwnResolver())
.build();
The resolve method should not throw any exception, but should return a Result.None instead. The factory method Result.none(String message) can be used for that.
Resolvers can be chained together. In the example we have two resolvers, one which resolves every variable to the String "FIRST" except the variable name "unknown" and the other resolves all to "FALLBACK".
public class FirstResolver extends VariableResolver {
@Override
Result resolve(String variableName) {
if ("unknown".equals(variableName)) {
return Result.none("this is unknown by me");
} else {
return Result.some("FIRST");
}
}
}
public class FallbackResolver extends VariableResolver {
@Override
Result resolve(String variableName) {
return Result.some("FALLBACK");
}
}
With a config file based on the first example
myInt: 12
myString: ${this} ${is} ${unknown}
the following code
VariableResolver resolver = new FirstResolver().withFallback(new FallbackResolver());
AppConfigr configr = AppConfigr.fromDirectory("path/to/config/files")
.withResolvingStrategy(resolver)
.build();
MyAppConfig config = configr.getConfig(AppConfig.class);
System.out.println("The value of myString is [" + config.getMyString() + "]");
would print
The value of myString is [FIRST FIRST FALLBACK]
The default format used by AppConfigr is yaml. But as AppConfigr is based on Jackson the supported format can be switched easily. If you want to use e.g. Json as configuration format for the example in the "Getting started" section like this
{
"myInt": "12",
"myString": "this is a string"
}
you only have to do the following
AppConfigr configr = AppConfigr.fromDirectory("path/to/config/files")
.withFactory(new JsonFactory())
.build();
Features like the variable resolving can be used for all formats supported by Jackson.