From 7e4ee4f720013c19e2caca81aa1bcfac3c2873c8 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 21 Jan 2014 13:58:16 +0000 Subject: [PATCH] Special case for YAML ParseException caused by bad document boundary YAML documents can be text literals, so some common typos can be misleading and not generate the expected exception (Boot fails to cast the document to a Map, rather than reporting the underlying exception). Fixes gh-235 --- .../boot/config/YamlProcessor.java | 5 ++++ .../ConfigFileApplicationListener.java | 19 +++++++------- .../boot/config/YamlProcessorTests.java | 26 +++++++++++++++++++ 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/spring-boot/src/main/java/org/springframework/boot/config/YamlProcessor.java b/spring-boot/src/main/java/org/springframework/boot/config/YamlProcessor.java index 15eb89d5895..ec707eeb315 100644 --- a/spring-boot/src/main/java/org/springframework/boot/config/YamlProcessor.java +++ b/spring-boot/src/main/java/org/springframework/boot/config/YamlProcessor.java @@ -167,6 +167,11 @@ public class YamlProcessor { private Map asMap(Object object) { // YAML can have numbers as keys Map result = new LinkedHashMap(); + if (!(object instanceof Map)) { + // A document can be a text literal + result.put("document", object); + return result; + } Map map = (Map) object; for (Entry entry : map.entrySet()) { Object value = entry.getValue(); diff --git a/spring-boot/src/main/java/org/springframework/boot/context/listener/ConfigFileApplicationListener.java b/spring-boot/src/main/java/org/springframework/boot/context/listener/ConfigFileApplicationListener.java index 33c9352c3fd..a4f15ad3c1c 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/listener/ConfigFileApplicationListener.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/listener/ConfigFileApplicationListener.java @@ -328,21 +328,22 @@ public class ConfigFileApplicationListener implements private PropertySource getPropertySource(String name, Resource resource, String profile, List loaders) { + if (resource == null || !resource.exists()) { + return null; + } String key = resource.getDescription() + (profile == null ? "" : "#" + profile); if (this.cached.containsKey(key)) { return this.cached.get(key); } boolean satisfied = true; for (PropertySourceLoader loader : loaders) { - if (resource != null && resource.exists()) { - if (loader.supports(resource)) { - PropertySource propertySource = loader.load(name, resource); - this.cached.put(key, propertySource); - return propertySource; - } - else { - satisfied = false; - } + if (loader.supports(resource)) { + PropertySource propertySource = loader.load(name, resource); + this.cached.put(key, propertySource); + return propertySource; + } + else { + satisfied = false; } } if (!satisfied) { diff --git a/spring-boot/src/test/java/org/springframework/boot/config/YamlProcessorTests.java b/spring-boot/src/test/java/org/springframework/boot/config/YamlProcessorTests.java index e52546900fd..8a7ab6cc55d 100644 --- a/spring-boot/src/test/java/org/springframework/boot/config/YamlProcessorTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/config/YamlProcessorTests.java @@ -24,6 +24,7 @@ import org.junit.rules.ExpectedException; import org.springframework.boot.config.YamlProcessor.MatchCallback; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.Resource; +import org.yaml.snakeyaml.parser.ParserException; import org.yaml.snakeyaml.scanner.ScannerException; import static org.junit.Assert.assertEquals; @@ -55,6 +56,31 @@ public class YamlProcessorTests { }); } + @Test + public void testStringResource() throws Exception { + this.processor.setResources(new Resource[] { new ByteArrayResource( + "foo # a document that is a literal".getBytes()) }); + this.processor.process(new MatchCallback() { + @Override + public void process(Properties properties, Map map) { + assertEquals("foo", map.get("document")); + } + }); + } + + @Test + public void testBadDocumentStart() throws Exception { + this.processor.setResources(new Resource[] { new ByteArrayResource( + "foo # a document\nbar: baz".getBytes()) }); + this.exception.expect(ParserException.class); + this.exception.expectMessage("line 2, column 1"); + this.processor.process(new MatchCallback() { + @Override + public void process(Properties properties, Map map) { + } + }); + } + @Test public void testBadResource() throws Exception { this.processor.setResources(new Resource[] { new ByteArrayResource(