4.6 Using @EachProperty to Drive Configuration
The @ConfigurationProperties annotation is great for a single configuration class, but sometimes you want multiple instances each with their own distinct configuration. That is where EachProperty comes in.
The @EachProperty annotation will create a ConfigurationProperties
bean for each sub-property within the given property. As an example consider the following class:
Using @EachProperty
import io.micronaut.context.annotation.Parameter;
import io.micronaut.context.annotation.EachProperty;
@EachProperty("test.datasource") (1)
public class DataSourceConfiguration {
private final String name;
private URI url = new URI("localhost");
public DataSourceConfiguration(@Parameter String name) (2)
throws URISyntaxException {
this.name = name;
}
public String getName() {
return name;
}
public URI getUrl() { (3)
return url;
}
public void setUrl(URI url) {
this.url = url;
}
}
Using @EachProperty
@EachProperty("test.datasource")
(1)
class DataSourceConfiguration {
final String name
URI url = new URI("localhost")
DataSourceConfiguration(@Parameter String name) (2)
throws URISyntaxException {
this.name = name
}
}
Using @EachProperty
@EachProperty("test.datasource") (1)
class DataSourceConfiguration (2)
@Throws(URISyntaxException::class)
constructor(@param:Parameter val name: String) {
(3)
var url = URI("localhost")
}
1 | The @EachProperty annotation defines the property name that should be handled. |
2 | The @Parameter annotation can be used to inject the name of the sub-property that defines the name of the bean (which is also the bean qualifier) |
3 | Each property of the bean is bound to configuration. |
The above DataSourceConfiguration
defines a url
property to configure one or many hypothetical data sources of some sort. The URLs themselves can be configured using any of the PropertySource instances evaluated to Micronaut:
Providing Configuration to @EachProperty
ApplicationContext applicationContext = ApplicationContext.run(PropertySource.of(
"test",
CollectionUtils.mapOf(
"test.datasource.one.url", "jdbc:mysql://localhost/one",
"test.datasource.two.url", "jdbc:mysql://localhost/two")
));
Providing Configuration to @EachProperty
ApplicationContext applicationContext = ApplicationContext.run(PropertySource.of(
"test",
[
"test.datasource.one.url": "jdbc:mysql://localhost/one",
"test.datasource.two.url": "jdbc:mysql://localhost/two"
]
))
Providing Configuration to @EachProperty
val applicationContext = ApplicationContext.run(PropertySource.of(
"test",
mapOf(
"test.datasource.one.url" to "jdbc:mysql://localhost/one",
"test.datasource.two.url" to "jdbc:mysql://localhost/two"
)
))
In the above example two data sources (called one
and two
) are defined under the test.datasource
prefix defined earlier in the @EachProperty
annotation. Each of these configuration entries triggers the creation of a new DataSourceConfiguration
bean such that the following test succeeds:
Evaluating Beans Built by @EachProperty
Collection<DataSourceConfiguration> beansOfType = applicationContext.getBeansOfType(DataSourceConfiguration.class);
assertEquals(2, beansOfType.size()); (1)
DataSourceConfiguration firstConfig = applicationContext.getBean(
DataSourceConfiguration.class,
Qualifiers.byName("one") (2)
);
assertEquals(
new URI("jdbc:mysql://localhost/one"),
firstConfig.getUrl()
);
Evaluating Beans Built by @EachProperty
when:
Collection<DataSourceConfiguration> beansOfType = applicationContext.getBeansOfType(DataSourceConfiguration.class)
assertEquals(2, beansOfType.size()) (1)
DataSourceConfiguration firstConfig = applicationContext.getBean(
DataSourceConfiguration.class,
Qualifiers.byName("one") (2)
)
then:
new URI("jdbc:mysql://localhost/one") == firstConfig.getUrl()
Evaluating Beans Built by @EachProperty
val beansOfType = applicationContext.getBeansOfType(DataSourceConfiguration::class.java)
assertEquals(2, beansOfType.size.toLong()) (1)
val firstConfig = applicationContext.getBean(
DataSourceConfiguration::class.java,
Qualifiers.byName("one") (2)
)
assertEquals(
URI("jdbc:mysql://localhost/one"),
firstConfig.url
)
1 | All beans of type DataSourceConfiguration can be retrieved using getBeansOfType |
2 | Individual beans can be achieved by using the byName qualifier. |