Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read multiple properties with same prefix in java spring?

I am having the property file with the following values. I want to read all the properties with same prefix excluding others using spring mvc.

test.cat=cat
test.dog=dog
test.cow=cow
birds=eagle

Environment.getProperty("test.cat");

This will return only 'cat' .

In the above property file, I want to get all the properties starting(prefix) with test excluding birds. In spring boot we can achieve this with @ConfigurationProperties(prefix="test"), but how to achieve the same in spring mvc.

like image 528
sub Avatar asked Dec 18 '17 17:12

sub


2 Answers

See this Jira ticket from Spring project for explanation why you don't see a method doing what you want. The snippet at the above link can be modified like this with an if statement in innermost loop doing the filtering. I assume you have a Environment env variable and looking for String prefix:

Map<String, String> properties = new HashMap<>();
if (env instanceof ConfigurableEnvironment) {
    for (PropertySource<?> propertySource : ((ConfigurableEnvironment) env).getPropertySources()) {
        if (propertySource instanceof EnumerablePropertySource) {
            for (String key : ((EnumerablePropertySource) propertySource).getPropertyNames()) {
                if (key.startsWith(prefix)) {
                    properties.put(key, propertySource.getProperty(key));
                }
            }
        }
    }
}
like image 122
Manos Nikolaidis Avatar answered Sep 30 '22 10:09

Manos Nikolaidis


I walked into a similar problem and solved it using the following code:

final var keyPrefix = "test";
final var map = new HashMap<String, Object>();
final var propertySources = ((AbstractEnvironment) environment).getPropertySources().stream().collect(Collectors.toList());
Collections.reverse(propertySources);
for (PropertySource<?> source : propertySources) {
    if (source instanceof MapPropertySource) {
        final var mapProperties = ((MapPropertySource) source).getSource();
        mapProperties.forEach((key, value) -> {
            if (key.startsWith(keyPrefix)) {
                map.put(key, value instanceof OriginTrackedValue ? ((OriginTrackedValue) value).getValue() : value);
            }
        });
    }
}
return map;

Difference with other solutions (like seen in Jira ticket) is that I reverse sort the property sources to ensure that the appropriate overriding of properties is happening. By default the property-sources are sorted from most important to least important (also see this article). So if you would not reverse the list before iterating you will always end up with the least important property values.

like image 30
Yoran van Oirschot Avatar answered Sep 30 '22 11:09

Yoran van Oirschot