Yaml values¶
Guicey introspects Configuration
object instance using jackson serialization api to allow accessing yaml configuration
values by yaml paths or sub-object types.
Introspected configuration:
- Bound directly in guice to inject direct values (by path) or sub objects
- Accessible from guice modules (with help of
ConfigurationAwareModule
interface) and bundles.
In both cases raw introspection result object is accessible: ru.vyarus.dropwizard.guice.module.yaml.ConfigurationTree
.
It could be used for config analysis, reporting or something else.
Warning
Jackson will see all properties which either have getter and setter or annotated with @JsonProperty
. For example,
public class MyConfig extends Configuration { private String one // visible (getter and setter) @JsonProperty private String two // visible (annotation) private String three // invisible (no getter) public void setOne(String one) { ... } public String getOne() { ... } public void setTwo(String two) { ... } public void setThree(String three) { ... } }
Tip
To prevent binding of configuration property use @JsonIgnore
on property getter
private String prop // dropwizard will set value from yaml public void setProp(Stirng prop) { ... } // property will not be available as path binding @JsonIgnore public String getProp() { ... }
Unique sub configuration¶
It is quite common to group configuration properties into sub objects like:
public class MyConfig extends Configuration { @JsonProperty AuthConfig auth; @JsonProperty DbConfig db; }
Guicey detects such unique objects and provides direct bindings for them:
@Inject @Config AuthConfig auth; @Inject @Config DbConfig db;
This is very useful for re-usable modules, which are not aware of your configuration object structure, but require only one sub configuration object:
public class MyConfig extends Configuration { @JsonProperty FeatureXConfig featureX; }
Somewhere in module service:
public class FeatureXService { @Inject @Config FeatureXConfig featureX; }
Important
Sub configuration object uniqueness is checked as direct match, so you may have
@JsonProperty SubConfig sub @JsonProperty SubConfigExt subExt
class SubConfigExt extends SubConfig
, but still both objects would be considered unique.
Whereas
@JsonProperty SubConfig sub1 @JsonProperty SubConfig sub2
Tip
Guicey bundles and guice modules also could use sub configuration objects directly:
GuiceyBootstrap#configuration(SubConfig.class) DropwizardAwareModule#configuration(SubConfig.class)
Configuration by path¶
All visible configuration paths values are directly bindable:
public class MyConfig extends Configuration { SubConf sub; } public class SubConf { String smth; List<String> values; }
@Inject @Config("sub") SubConf sub; @Inject @Config("sub.smth") String smth; @Inject @Config("sub.values") List<String> values;
Note
Path bindings are available even for null values. For example, if sub configuration object is null, all it's sub paths will still be available (by class declarations). The only exception is conditional mappin like dropwizard "server" when available paths could change, depending on configuration (what configuration class will be used)
Note
Generified types are bound only with generics (with all available type information).
If you will have SubConf<T> sub
in config, then it will be bound with correct generic SubConfig<String>
(suppose generic T is declared as String).
Value type, declared in configuration class is used for binding, but there are two exceptions.
If declared type is declared as collection (Set, List, Map) implementation then binding will use base collection interface:
ArrayList<String> value @Inject @Config("value") List<String> vlaue;
If, for some (unforgivable) reason, property is declared as Object in configuration, then binding type will depend on value presence:
@Config("path") Object val
- when value is null@Config("path") ValueType val
- actual value type, when value is not null
It is assumed that in such case value would be always present (some sort of property-selected binding, like dropwizard "server").
Tip
You can declare you own additional bindings using ConfigurationTree
(accessible from guice module),
which contains all paths information (including declaration and actual types with generics).
Introspected configuration¶
ConfigurationTree
object provides access for introspected configuration tree:
getRootTypes()
- all classes in configuration hierarchy (including interfaces)getPaths()
- all paths (including all steps ("sub", "sub.value"))getUniqueTypePaths()
- paths of unique sub configuration types
Each path item (ConfigPath
) contains:
- Root path reference ("sub.value" reference "sub")
- Child sub-paths ("sub" reference "sub.value")
- Declaration class (type used in configuration class)
- Value type (type of actual value; when value null - declaration type (but they still could be different for collections))
- Current path name
- Current path value
- Generics for declaration and value types (may be incomplete for value type)
- Custom type marker: contains sub paths or just looks like sub configuration
- Declaration type (class where property was declared - configuration object containing property)
You can traverse up or down from any path (tree structure).
ConfigurationTree
provides basic search methods (more as usage example):
findByPath(String)
- search path by case-insensitive matchfindAllByType(Class)
- find all paths with assignable declared valuefindAllFrom(Class<? extends Configuration>)
- find all paths, started in specified configuration classfindAllRootPaths()
- get all root paths (1st level paths)findAllRootPathsFrom(Class<? extends Configuration>)
- all 1st level paths of configuration classvalueByPath(String)
- return path value or null if value null or path not existsvaluesByType(Class)
- all not null values with assignable typevalueByType(Class)
- first not null value with assignable typevalueByUniqueDeclaredType(Class)
- value of unique sub conifguration or null if value is null or config is not unique
Paths are sorted by configuration class (to put custom properties upper) and by path name (for predictable paths order).
Disable configuration introspection¶
Introspection process should not fail application startup. In worse case it will show warning log that property can't be introspected:
WARN [2018-07-23 09:11:13,034] ru.vyarus.dropwizard.guice.module.yaml.ConfigTreeBuilder: Can't bind configuration path 'sub.sample' due to IllegalArgumentException: Failed to getValue() with method ru.vyarus.dropwizard.guice.yaml.support.FailedGetterConfig#getSample(0 params): null. Enable debug logs to see complete stack trace or use @JsonIgnore on property getter.
Such warnings could be hidden by using @JsonIgnore
on property getter.
If this is not enough, or you need to avoid configuration introspection for other reasons, you can disable introspection completely with option:
GuiceBundle.builder() .option(GuiceyOptions.BindConfigurationByPath, false) ...
When introspection disabled, only configuration object would be bound and
bindings by path would not be available. Note that even ConfigurationTree
object will not
contain configuration paths (option completely disables introspection mechanism).