Just to share with others, maybe someone finds this useful.
The Entire solution is related with bean which extends PropertySourcesPlaceholderConfigurer.
- Part is to add another property source to the existing list of property sources.
In my case I needed application.property which is stored in some jar file.
For that purpose, we have JarPropertiesPropertySource:
public class JarPropertiesPropertySource extends MapPropertySource implements Logger {
@SuppressWarnings({"unchecked", "rawtypes"})
public JarPropertiesPropertySource(String name, Properties source) {
super(name, (Map) source);
}
protected JarPropertiesPropertySource(String name, Map<String, Object> source) {
super(name, source);
}
}
And the main logic is in CustomPropertySourcesPlaceholderConfigurer bean:
public class CustomPropertySourcesPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer implements Logger {
@Override
public PropertySources getAppliedPropertySources() throws IllegalStateException {
final MutablePropertySources mps = new MutablePropertySources();
// Get existing PropertySources
PropertySources ps = super.getAppliedPropertySources();
ps.forEach(propSource -> mps.addLast(new PropertySourceProxy(propSource)));
// Add JAR property source
mps.addLast(new JarPropertiesPropertySource("jar", ....))
return mps;
}
}
- We need to support property key overloading. For example, if we have property 'serviceA|data.user', and if that property doesn't exist then try to find property 'data/user'.
For that purpose, we need to proxy property sources, and each property from super.getAppliedPropertySources() wrap inside proxy PropertySourceProxy. So each spring call for getProperty will go through proxy method and check variations:
.
public class PropertySourceProxy extends PropertySource {
public PropertySourceProxy(PropertySource propertySource) {
super(propertySource.getName(), propertySource.getSource());
Object o = propertySource.getSource();
if (o instanceof StandardEnvironment) {
ConfigurableEnvironment ce = (ConfigurableEnvironment) o;
MutablePropertySources cemps = ce.getPropertySources();
cemps.forEach(propSource -> {
cemps.replace(propSource.getName(), new PropertySourceProxy(propSource));
});
}
}
@Override
public Object getProperty(String name) {
Object value = null;
if (name != null) {
int index = name.indexOf("|");
if (index != -1) {
String newName = name.substring(index + 1);
value = super.getProperty(newName);
}
}
if (value == null)
value = super.getProperty(name);
return value;
}
}