I'm wondering, if there is a generic way to fill a map with properties you just know the prefix.
Assuming there are a bunch of properties like
namespace.prop1=value1 namespace.prop2=value2 namespace.iDontKnowThisNameAtCompileTime=anothervalue
I'd like to have a generic way to fill this property inside a map, something like
@Component @ConfigurationProperties("namespace") public class MyGenericProps { private Map<String, String> propmap = new HashMap<String, String>(); // setter and getter for propmap omitted public Set<String> returnAllKeys() { return propmap.keySet(); } }
Or is there another convenient way to collect all properties with a certain prefix, instead of iterating over all PropertySources in the environment?
Thanks Hansjoerg
How to Inject a Map From a YAML File. Spring Boot has taken data externalization to the next level by providing a handy annotation called @ConfigurationProperties. This annotation is introduced to easily inject external properties from configuration files directly into Java objects.
@ConfigurationProperties allows to map the entire Properties and Yaml files into an object easily. It also allows to validate properties with JSR-303 bean validation. By default, the annotation reads from the application.
As long as you're happy having every property added into the map, rather than just those that you don't know in advance, you can do this with @ConfigurationProperties
. If you want to grab everything that's beneath namespace
then you need to use an empty prefix and provide a getter for a map named namespace
:
@ConfigurationProperties("") public class CustomProperties { private final Map<String, String> namespace = new HashMap<>(); public Map<String, String> getNamespace() { return namespace; } }
Spring Boot uses the getNamespace
method to retrieve the map so that it can add the properties to it. With these properties:
namespace.a=alpha namespace.b=bravo namespace.c=charlie
The namespace
map will contain three entries:
{a=alpha, b=bravo, c=charlie}
If the properties were nested more deeply, for example:
namespace.foo.bar.a=alpha namespace.foo.bar.b=bravo namespace.foo.bar.c=charlie
Then you'd use namespace.foo
as the prefix and rename namespace
and getNamespace
on CustomProperties
to bar
and getBar
respectively.
Note that you should apply @EnableConfigurationProperties
to your configuration to enable support for @ConfigurationProperties
. You can then reference any beans that you want to be processed using that annotation, rather than providing an @Bean
method for them, or using @Component
to have them discovered by component scanning:
@SpringBootApplication @EnableConfigurationProperties(CustomProperties.class) public class YourApplication { // … }
In addition to this, my problem was that I didn't had multiple simple key/value properties but whole objects:
zuul: routes: query1: path: /api/apps/test1/query/** stripPrefix: false url: "https://test.url.com/query1" query2: path: /api/apps/test2/query/** stripPrefix: false url: "https://test.url.com/query2" index1: path: /api/apps/*/index/** stripPrefix: false url: "https://test.url.com/index"
Following Jake's advice I tried to use a Map with a Pojo like this:
@ConfigurationProperties("zuul") public class RouteConfig { private Map<String, Route> routes = new HashMap<>(); public Map<String, Route> getRoutes() { return routes; } public static class Route { private String path; private boolean stripPrefix; String url; // [getters + setters] } }
Works like a charm, Thanks!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With