Skip to content

Instantly share code, notes, and snippets.

@rlindooren
Created May 22, 2020 11:44
Show Gist options
  • Save rlindooren/15e692516e66050056b5827746668dbe to your computer and use it in GitHub Desktop.
Save rlindooren/15e692516e66050056b5827746668dbe to your computer and use it in GitHub Desktop.
Spring: inject Map from additional YAML properties file with @propertysource and @ConfigurationProperties
someMap:
key1: [a, b, c]
key2: [d, e, f]
package foo;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import java.util.List;
import java.util.Map;
@Configuration
// E.g. as environment variable: `EXPORT ADDITIONAL_YAML_CONFIG_PATH=file:/path/to/additional.yaml`
@PropertySource(value = "${additional-yaml-config-path}", factory = YamlPropertySourceFactory.class)
@ConfigurationProperties(prefix = "additional-yaml-config")
@Data
public class SomeProperties {
private Map<String, List<String>> someMap;
}
package foo;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;
import java.util.Properties;
/**
* Makes it possible to use YAML as input for @PropertySource and @ConfigurationProperties.
* Originally found here: https://www.baeldung.com/spring-yaml-propertysource,
* but adapted to be able to parse maps and keep their original structure (not as properties for each key in the map).
*/
public class YamlPropertySourceFactory implements PropertySourceFactory {
public static String prefix = "additional-yaml-config";
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) {
final YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean() {
// Overriding this method so that we can add a map, as an actual map, to the properties,
// without it being converted to separate properties per key
@Override
protected Properties createProperties() {
final Properties result = new Properties();
process((properties, map) ->
map.keySet().forEach(key -> {
// Add the prefix to the key
// The prefix allows: @ConfigurationProperties(prefix = "additional-yaml-config")
final String keyInProperties = String.format("%s.%s", prefix, key);
result.put(keyInProperties, map.get(key));
})
);
return result;
}
};
factory.setResources(encodedResource.getResource());
final Properties properties = factory.getObject();
return new PropertiesPropertySource(encodedResource.getResource().getFilename(), properties);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment