@Retention(RUNTIME)
@Target({METHOD,FIELD,PARAMETER})
public static @interface Config.Value
ConfigMapper
implementation.
The first option for generic Config to JavaBean deserialization works just with class with no-parameter constructor. Each JavaBean property value is then set by value mapped from appropriate configuration node. Each public setter method and public non-final fields are taken as JavaBean properties that will be set. The deserialization process is applied recursively on each property.
Use Config.Transient
annotation to exclude setter or field from set of processed JavaBean properties.
By default JavaBean property name is used as config key to get
configuration node.
The config key can be customized by key()
attribute. Use the annotation on public setter or public field.
Annotation on method has precedence over annotation used on field. The second one is ignored.
If the appropriate configuration node does not exist it is possible to specify default value:
withDefaultSupplier()
- instance of supplier class is used to get default value of target type; orwithDefault()
- default value in String
form that will be mapped to target type
by associated ConfigMapper
withDefaultSupplier
is used
and withDefault
is ignored.
public class AppConfig {
private String greeting;
private int pageSize;
private List<Integer> range;
public AppConfig() { // <1>
}
public void setGreeting(String greeting) { // <2>
this.greeting = greeting;
}
@Config.Value(key = "page-size", withDefault = "10") // <3>
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
@Config.Value(withDefaultSupplier = DefaultRangeSupplier.class) // <4>
public void setRange(List<Integer> basicRange) {
this.range = basicRange;
}
//...
public static class DefaultRangeSupplier // <5>
implements Supplier<List<Integer>> {
@Override
public List<Integer> get() {
return CollectionsHelper.listOf(0, 10);
}
}
}
greeting
is not customized; will be set from config node with greeting
key, if exists;pageSize
customizes key of config node to page-size
;
if the config node does not exist, value "10"
will be mapped to int
;
range
will be set from config node with same range
key;
if the config node does not exist, DefaultRangeSupplier
instance will be used to get default value;
DefaultRangeSupplier
is used to supply List<Integer>
value.
The second option is to provide factory public static method from
with parameters set from configuration.
Or public "factory" constructor with parameters can be used too.
public class AppConfig {
private final String greeting;
private final int pageSize;
private final List<Integer> basicRange;
private AppConfig(String greeting, int pageSize, List<Integer> basicRange) {
this.greeting = greeting;
this.pageSize = pageSize;
this.basicRange = basicRange;
}
//...
// FACTORY METHOD
public static AppConfig from(@Config.Value(key = "greeting", withDefault = "Hi")
String greeting,
@Config.Value(key = "page-size", withDefault = "10")
int pageSize,
@Config.Value(key = "basic-range",
withDefaultSupplier = DefaultBasicRangeSupplier.class)
List<Integer> basicRange) {
return new AppConfig(greeting, pageSize, basicRange);
}
}
The third option is to provide Builder accessible by public static builder()
method.
The Builder instances is initialized via public setters or fields, similar to the first deserialization option.
Finally, Builder has build()
method that creates new instances of a bean.
public class AppConfig {
private final String greeting;
private final int pageSize;
private final List<Integer> basicRange;
private AppConfig(String greeting, int pageSize, List<Integer> basicRange) {
this.greeting = greeting;
this.pageSize = pageSize;
this.basicRange = basicRange;
}
// BUILDER METHOD
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String greeting;
private int pageSize;
private List<Integer> basicRange;
private Builder() {
}
@Config.Value(withDefault = "Hi")
public void setGreeting(String greeting) {
this.greeting = greeting;
}
@Config.Value(key = "page-size", withDefault = "10")
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
@Config.Value(key = "basic-range",
withDefaultSupplier = DefaultBasicRangeSupplier.class)
public void setBasicRange(List<Integer> basicRange) {
this.basicRange = basicRange;
}
// BUILD METHOD
public AppConfig build() {
return new AppConfig(greeting, pageSize, basicRange);
}
}
}
Configuration example:
{
"app": {
"greeting": "Hello",
"page-size": 20,
"range": [ -20, 20 ]
}
}
Getting app
config node as AppConfig
instance:
AppConfig appConfig = config.get("app").as(AppConfig.class);
assert appConfig.getGreeting().equals("Hello");
assert appConfig.getPageSize() == 20;
assert appConfig.getRange().get(0) == -20;
assert appConfig.getRange().get(1) == 20;
In this case default values where not used because JSON contains all expected nodes.
The annotation cannot be applied on same JavaBean property together with Config.Transient
.
Config.Transient
Modifier and Type | Optional Element | Description |
---|---|---|
java.lang.String |
key |
Specifies a key of configuration node to be used to set JavaBean property value from.
|
java.lang.String |
withDefault |
Specifies default value in form of single String value
that will be used to set JavaBean property value in case configuration does not contain a config node
of appropriate config key.
|
java.lang.Class<? extends java.util.function.Supplier> |
withDefaultSupplier |
Specifies supplier of default value
that will be used to set JavaBean property value in case configuration does not contain config node
of appropriate config key.
|
java.lang.String key
If not specified original JavaBean property name is used.
java.lang.String withDefault
In case withDefaultSupplier()
is also used current value is ignored.
java.lang.Class<? extends java.util.function.Supplier> withDefaultSupplier
Default value is used in case appropriate config value is not set.
In case withDefault()
is also used this one has higher priority and will be used.
Copyright © 2018 Oracle Corporation. All rights reserved.