The Justconfig library provides easy access to configuration properties using interface proxy instances
The Justconfig library provides easy access to configuration properties. By simply specifying an interface describing your configuration values you can access those values without a hassle, independent of their source.
Justconfig has no dependencies.
If you want to avoid parsing and navigating various configuration sources and instead
have a slick, nifty, object which lets you access your configuration with compile time type safety.
Take a look at a sample!
This example showcases a simple usage, leveraging annotation interfaces' ability to specify default values with method declaration
public class Simple {
private static @interface ConfigSpecs {
int poolSize() default 16;
String threadGroupName() default "myexecs";
}
private static final ConfigSpecs CONFIG = ConfigurationProxyBuilder.newBuilder(new SystemPropertiesConfigurationSource())
.build(ConfigSpecs.class);
public static void main( String[] args ) throws InstantiationException, IllegalAccessException{
System.setProperty("threadGroupName", "configuredValue");
assertEquals(16, CONFIG.poolSize());
assertEquals("configuredValue", CONFIG.threadGroupName());
}
}
There are a few, very simple, core concepts in Justconfig:
A Configuration source retrieves simple values (Strings or primitives) for a String configuration property name. A simpler subset of Apache Configuration API's Configuration interface.
Justconfig comes out of the box with these configuration sources:
New Configuration sources can be easily added by implementing the ConfigurationSource interface or extending the ConfigurationSourceBase class which helps with String backed configuration sources.
Configuration spec is your definition of what the configuration holds. You define one by defining an interface or an annotation like the following
public @interface ConfigSpecs {
int poolSize() default 16;
String threadGroupName();
}
public interface ConfigSpecs2 {
Boolean poolSize();
String threadGroupName();
}
Justconfig will get you an instance of the interface, working just like how you think it will.
If you're wondering why pick or not pick annotations over interfaces, these are the key differences:
These are the core component you will interactive with, built using a ConfigurationProxyBuilder are an implementation of a given Configuration Spec backed by a Configuration Source
While the return types for methods in annotations are from a constant set, interfaces can have other return values.
This is where Value Reader Services come in to play, an implementation accepts certain types that it can obtain from a configuration, and does so when such a value is requested.
Look at EnumValueReaderService for a simple example:
public class EnumValueReaderService implements ValueReaderService {
/**
* return true iff the type is an enum.
*/
public boolean readable(Class<?> type) {
return Enum.class.isAssignableFrom(type);
}
/**
* Reads an enum constant using the enum's valueOf method
*/
@SuppressWarnings({ "unchecked" })
public Enum readValue(ClassLoader loader, ConfigurationSource config,
String name, Class<?> type)
throws IllegalArgumentException {
String enumName = config.getString(name);
if(enumName == null) {
return null;
}
Class<? extends Enum> eClass = type.asSubclass(Enum.class);
return Enum.valueOf(eClass, enumName);
}
}
Justconfig by default looks for ValueReaderServices using Java's ServiceLoader, allowing you to easily implement value readers for more types or plug in libraries that do.