-
Notifications
You must be signed in to change notification settings - Fork 180
Configuration Mapping
As part of initializing an object, Governator can assign configuration values to object fields. To use this feature, you must bind an instance that implements ConfigurationProvider in the bootstrap phase or annotation a ConfigurationProvider with @AutoBindSingleton. Governator provides a few default implementations to use. Then, annotate fields with @Configuration.
The ConfigurationProvider is used to provide configuration values from configuration names as specified by @Configuration annotations. Governator bundles three implementations that you can use:
Class | Description |
---|---|
SystemConfigurationProvider | Returns System properties via System.getProperty()
|
PropertiesConfigurationProvider | Returns values from a Properties object |
ArchaiusConfigurationProvider | Returns values using Netflix’s Archaius |
Additionally, CompositeConfigurationProvider can be used to chain ConfigurationProviders together.
There are two ways to identify the ConfigurationProvider to Governator:
- Annotate the ConfigurationProvider with @AutoBindSingleton (making sure it is in the set of packages passed to the classpath scanner).
- Bind the ConfigurationProvider in the bootstrap module.
Here is an example of binding in the bootstrap module:
LifecycleInjector.builder()
.withBootstrapModule
(
new BootstrapModule()
{
@Override
public void configure(Binder binder, RequiredAssetBinder requiredAssetBinder)
{
binder.bindConfigurationProvider().to(MyProvider.class);
}
}
)
You can annote methods you want called prior to configuration mapping. E.g.:
@PreConfiguration
public void myConfigurationLoader()
{
// gets called prior to configuration mapping and prior to PostConstruct methods
}
Fields annotated with @Configuration will get assigned configuration values based on the type of the field and the value set in the annotation. Here’s an example:
@Configuration("configs.qty.things")
private int numberOfThings = 10;
For the above, Governator will call ConfigurationProvider.has(“configs.qty.things”) (note the argument is actually a ConfigurationKey – see below). If it returns false, “numberOfThings” will stay set to 10 – i.e. 10 is the default value. If it returns true, “numberOfThings” is assigned the value returned by ConfigurationProvider.getInteger(“configs.qty.things”). If “numberOfThings” was a String, ConfigurationProvider.getString(“configs.qty.things”) would be called, etc.
Some configuration parameters may change at runtime and it would be desirable to have the new value picked up immediately. To specify a dynamic configuration simply define the field as a Supplier. Here’s an example,
@Configuration("configs.qty.things")
private Supplier<Integer> numberOfThings = Suppliers.ofInstance(10);
Governator will bind a supplier to the internal dynamic mechanism provided by the ConfigurationProvider. Note that special consideration must be given to properties that have yet to be specified at the configuration binding phase but that can be specified later at runtime. For example, the above property ‘configs.qty.things’ may not exist in the configuration when the object is configured but may be defined in the future. To make the ConfigurationProvider aware of this property you must provide it with a property ownership policy. The ownership policy tells Governator that certain properties belong to a provider regardless of whether they exist or not. Several policies are provided and can be specified on the ArchaiusConfigurationProvider as follows,
ArchaiusConfigurationProvider.builder()
.withOwnershipPolicy(ConfigurationOwnershipPolicies.ownsAll())
.build()
Each method of the ConfigurationProvider takes a ConfigurationKey
as an argument as opposed to a simple string. The ConfigurationKey enables a convention for providing variables within the @Configuration value. Governator will parse the value into tokens. Tokens can be either a literal value or a variable substitution. Variables are specified as ${variable-name}
. The ConfigurationKey has a method to apply variables and return the applied key:
public String getKey(Map<String, String> variableValues);
The variableValues maps a variable name to its value. Some examples:
Value | variableValues | Actual Key |
---|---|---|
${stage}.server | “stage” → “test” | test.server |
password.${user}.${month} | “user” → “jz”, “month” → “oct” | password.jz.oct |
ConfigurationKey also has a method to get the list of variable names present in the @Configuration value.
Governator provides a documentation mechanism for configuration. When LifecycleManager.start() is called (after configuration assignments) Governator will log detailed information about the configuration values used in your application. In support of this, you should specify descriptive documentation in your @Configuration annotations via the optional documentation property. E.g.
@Configuration
(
value = "configs.qty.things",
documentation = "This controls the number of things used."
)
private int numberOfThings = 10;
The configuration logging looks like this:
PROPERTY FIELD DEFAULT VALUE DESCRIPTION prop.name.1 com.foo.Bar#aBool false true This is a boolean other.prop com.foo.Bar#xyz something another thing This does something
Governator uses ConfigurationProvider’s various methods to obtain a value which matches with the target field data type. However, in cases where the property’s value is wrongly configured, such that the value can not be converted to the target data type, Governator initialization will fail. This behavior is suitable for most of the cases where the configured field is critical for the functioning of the module. However, in cases where the configured field can work well with a default value, this behavior is disruptive. In such a case, in order to ignore the type mismatch, one can set the property “ignoreTypeMismatch” to true. This will ignore any type mismatch that occurs during configuration.
. E.g.
@Configuration
(
value = "configs.qty.things",
documentation = "This controls the number of things used.",
ignoreTypeMismatch = true
)
private int numberOfThings = 10;
In the above case, if the value of the property “configs.qty.things” is set to “foo”, the property value will be ignored. The field numberOfThings will remain set to 10 i.e. the default value above.
Governator determines that a failure to retrieve a value was a type mismatch, if the ConfigurationProvider throws any of the following exceptions, upon property retrieval:
- java.lang.IllegalArgumentException
- org.apache.commons.configuration.ConversionException
- Home
- Getting Started
- Bootstrapping
- Lifecycle Management
- Auto Binding
- Module-Dependencies
- Warm Up
- Configuration Mapping
- Field Validation
- Lazy Singleton
- Concurrent Singleton
- Generic Binding Annotations
- LifecycleListener
- Governator Phases
- Grapher Integration
- JUnit Testing
- FAQ
- Best Practices
- Spring, PicoContainer, Etc.
- Javadoc
- End-to-End Examples