
Originally Posted by
zakhrim
Maybe it's a silly question, but just to be sure, did you add the line
HTML Code:
<context:property-placeholder location="classpath:/META-INF/....." />
to your app config?
Regards,
Stefano
Yes, I added the property-placeholder, other properties were being resolved.
My current solution is:
Code:
/**
* Allows for making a Map from a properties file from a classpath location available in a bean factory. Can be used to
* populate any bean property of type Map via a bean reference.
*
* <p>
* Supports loading from a properties file and/or setting local properties on this FactoryBean. The created Properties
* instance will be merged from loaded and local values. If neither a location nor local properties are set, an
* exception will be thrown on initialization.
*
* @see #setLocation
* @see #setProperties
* @see #setLocalOverride
* @see java.util.Properties
*/
public class MapFactoryBean extends PropertiesLoaderSupport implements FactoryBean<Map<String, String>> {
private static final Logger LOG = LoggerFactory.getLogger(MapFactoryBean.class);
private String mapPropertyName;
@Override
public Map<String, String> getObject() throws IOException {
Properties props = mergeProperties();
Map<String, String> map = Maps.newHashMap();
boolean valid = true;
String keyList = props.getProperty(mapPropertyName + ".list");
if (StringUtils.isEmpty(keyList)) {
LOG.error("Failed to read map '{}', missing list property.", mapPropertyName);
valid = false;
} else {
valid = createMap(props, map, keyList);
}
if (valid) {
return map;
} else {
throw new IllegalStateException("Failed to read map '" + mapPropertyName + "'.");
}
}
private boolean createMap(final Properties props, final Map<String, String> map, final String keyList) {
boolean valid = true;
String[] keys = StringUtils.split(keyList, ",");
for (String key : keys) {
String value = props.getProperty(mapPropertyName + "." + key);
if (value == null) {
LOG.error("Failed to read map '{}': Missing value for key '{}'", mapPropertyName, key);
valid = false;
} else {
map.put(key, value);
}
}
return valid;
}
@Override
public Class<?> getObjectType() {
return Map.class;
}
@Override
public boolean isSingleton() {
return true;
}
/**
* @param mapPropertyName
* the mapPropertyName to set
*/
public void setMapPropertyName(final String mapPropertyName) {
this.mapPropertyName = mapPropertyName;
}
}
And configure it like this:
Code:
<bean id="sampleBean" class="com.example.SampleBeanl">
<property name="mapName">
<bean class="com.example.spring.MapFactoryBean">
<property name="location" value="classpath:example.properties" />
<property name="mapPropertyName" value="com.example.map" />
</bean>
</property>
</bean>
And this works. (And I now see I won't need the list property, I could just iterate over all the properties and only pick the ones starting with the mapPropertyName.)