YamlPropertiesFactoryBean consistently exposes String values

Issue: SPR-14737
(cherry picked from commit 74c6188)
This commit is contained in:
Juergen Hoeller
2016-09-25 21:05:40 +02:00
parent 0bb2cfe440
commit 3346c594e4
8 changed files with 148 additions and 94 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,12 +25,16 @@ import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
/**
* Factory for a Map that reads from a YAML source. YAML is a nice human-readable
* format for configuration, and it has some useful hierarchical properties. It's
* more or less a superset of JSON, so it has a lot of similar features. If
* multiple resources are provided the later ones will override entries in the
* earlier ones hierarchically - that is all entries with the same nested key of
* type Map at any depth are merged. For example:
* Factory for a {@code Map} that reads from a YAML source, preserving the
* YAML-declared value types and their structure.
*
* <p>YAML is a nice human-readable format for configuration, and it has some
* useful hierarchical properties. It's more or less a superset of JSON, so it
* has a lot of similar features.
*
* <p>If multiple resources are provided the later ones will override entries in
* the earlier ones hierarchically; that is, all entries with the same nested key
* of type {@code Map} at any depth are merged. For example:
*
* <pre class="code">
* foo:
@@ -62,6 +66,7 @@ import org.springframework.beans.factory.InitializingBean;
* with the value in the second, but its nested values are merged.
*
* @author Dave Syer
* @author Juergen Hoeller
* @since 4.1
*/
public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean<Map<String, Object>>, InitializingBean {
@@ -104,10 +109,10 @@ public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean<Map
/**
* Template method that subclasses may override to construct the object
* returned by this factory. The default implementation returns the
* merged Map instance.
* returned by this factory.
* <p>Invoked lazily the first time {@link #getObject()} is invoked in
* case of a shared singleton; else, on each {@link #getObject()} call.
* <p>The default implementation returns the merged {@code Map} instance.
* @return the object returned by this factory
* @see #process(java.util.Map, MatchCallback)
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@ import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.parser.ParserException;
import org.yaml.snakeyaml.reader.UnicodeReader;
import org.springframework.core.CollectionFactory;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -45,6 +46,7 @@ import org.springframework.util.StringUtils;
* Base class for YAML factories.
*
* @author Dave Syer
* @author Juergen Hoeller
* @since 4.1
*/
public abstract class YamlProcessor {
@@ -217,7 +219,7 @@ public abstract class YamlProcessor {
}
private boolean process(Map<String, Object> map, MatchCallback callback) {
Properties properties = new Properties();
Properties properties = CollectionFactory.createStringAdaptingProperties();
properties.putAll(getFlattenedMap(map));
if (this.documentMatchers.isEmpty()) {
@@ -302,21 +304,23 @@ public abstract class YamlProcessor {
}
}
else {
result.put(key, value != null ? value : "");
result.put(key, (value != null ? value : ""));
}
}
}
/**
* Callback interface used to process properties in a resulting map.
* Callback interface used to process the YAML parsing results.
*/
public interface MatchCallback {
/**
* Process the properties.
* @param properties the properties to process
* @param map a mutable result map
* Process the given representation of the parsing results.
* @param properties the properties to process (as a flattened
* representation with indexed keys in case of a collection or map)
* @param map the result map (preserving the original value structure
* in the YAML document)
*/
void process(Properties properties, Map<String, Object> map);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,13 +21,23 @@ import java.util.Properties;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.CollectionFactory;
/**
* Factory for Java Properties that reads from a YAML source. YAML is a nice
* human-readable format for configuration, and it has some useful hierarchical
* properties. It's more or less a superset of JSON, so it has a lot of similar
* features. The Properties created by this factory have nested paths for
* hierarchical objects, so for instance this YAML
* Factory for {@link java.util.Properties} that reads from a YAML source,
* exposing a flat structure of String property values.
*
* <p>YAML is a nice human-readable format for configuration, and it has some
* useful hierarchical properties. It's more or less a superset of JSON, so it
* has a lot of similar features.
*
* <p><b>Note: All exposed values are of type {@code String}</b> for access through
* the common {@link Properties#getProperty} method (e.g. in configuration property
* resolution through {@link PropertyResourceConfigurer#setProperties(Properties)}).
* If this is not desirable, use {@link YamlMapFactoryBean} instead.
*
* <p>The Properties created by this factory have nested paths for hierarchical
* objects, so for instance this YAML
*
* <pre class="code">
* environments:
@@ -39,7 +49,7 @@ import org.springframework.beans.factory.InitializingBean;
* name: My Cool App
* </pre>
*
* is transformed into these Properties:
* is transformed into these properties:
*
* <pre class="code">
* environments.dev.url=http://dev.bar.com
@@ -57,7 +67,7 @@ import org.springframework.beans.factory.InitializingBean;
* - foo.bar.com
* </pre>
*
* becomes Java Properties like this:
* becomes properties like this:
*
* <pre class="code">
* servers[0]=dev.bar.com
@@ -66,6 +76,7 @@ import org.springframework.beans.factory.InitializingBean;
*
* @author Dave Syer
* @author Stephane Nicoll
* @author Juergen Hoeller
* @since 4.1
*/
public class YamlPropertiesFactoryBean extends YamlProcessor implements FactoryBean<Properties>, InitializingBean {
@@ -116,7 +127,7 @@ public class YamlPropertiesFactoryBean extends YamlProcessor implements FactoryB
* @see #process(MatchCallback) ()
*/
protected Properties createProperties() {
final Properties result = new Properties();
final Properties result = CollectionFactory.createStringAdaptingProperties();
process(new MatchCallback() {
@Override
public void process(Properties properties, Map<String, Object> map) {