diff --git a/spring-boot-project/spring-boot-devtools/pom.xml b/spring-boot-project/spring-boot-devtools/pom.xml
index ec2c76f602cc..9af7e352ad79 100644
--- a/spring-boot-project/spring-boot-devtools/pom.xml
+++ b/spring-boot-project/spring-boot-devtools/pom.xml
@@ -206,6 +206,11 @@
thymeleaf-spring5
test
+
+ org.yaml
+ snakeyaml
+ test
+
nz.net.ultraq.thymeleaf
thymeleaf-layout-dialect
diff --git a/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessor.java b/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessor.java
index 8c1a4e5069cc..4305ef20d441 100644
--- a/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessor.java
+++ b/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessor.java
@@ -19,18 +19,23 @@
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
-import java.util.Properties;
+import java.util.Set;
import java.util.function.Function;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.devtools.system.DevToolsEnablementDeducer;
import org.springframework.boot.env.EnvironmentPostProcessor;
+import org.springframework.boot.env.PropertiesPropertySourceLoader;
+import org.springframework.boot.env.PropertySourceLoader;
+import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.ConfigurableEnvironment;
-import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.FileSystemResource;
-import org.springframework.core.io.support.PropertiesLoaderUtils;
+import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
@@ -52,6 +57,17 @@ public class DevToolsHomePropertiesPostProcessor implements EnvironmentPostProce
private static final String CONFIG_PATH = "/.config/spring-boot/";
+ private static final Set PROPERTY_SOURCE_LOADERS;
+
+ static {
+ Set propertySourceLoaders = new HashSet<>();
+ propertySourceLoaders.add(new PropertiesPropertySourceLoader());
+ if (ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) {
+ propertySourceLoaders.add(new YamlPropertySourceLoader());
+ }
+ PROPERTY_SOURCE_LOADERS = Collections.unmodifiableSet(propertySourceLoaders);
+ }
+
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
if (DevToolsEnablementDeducer.shouldEnable(Thread.currentThread())) {
@@ -88,15 +104,23 @@ private void addPropertySource(List> propertySources, String f
private void addPropertySource(List> propertySources, FileSystemResource resource,
Function propertySourceNamer) {
try {
- Properties properties = PropertiesLoaderUtils.loadProperties(resource);
String name = propertySourceNamer.apply(resource.getFile());
- propertySources.add(new PropertiesPropertySource(name, properties));
+ for (PropertySourceLoader loader : PROPERTY_SOURCE_LOADERS) {
+ if (canLoadFileExtension(loader, resource.getFilename())) {
+ propertySources.addAll(loader.load(name, resource));
+ }
+ }
}
catch (IOException ex) {
throw new IllegalStateException("Unable to load " + resource.getFilename(), ex);
}
}
+ private boolean canLoadFileExtension(PropertySourceLoader loader, String name) {
+ return Arrays.stream(loader.getFileExtensions())
+ .anyMatch((fileExtension) -> StringUtils.endsWithIgnoreCase(name, fileExtension));
+ }
+
protected File getHomeFolder() {
String home = System.getProperty("user.home");
if (StringUtils.hasLength(home)) {
diff --git a/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessorTests.java b/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessorTests.java
index 65e7eb29da04..daa7796bdc35 100644
--- a/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessorTests.java
+++ b/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessorTests.java
@@ -20,6 +20,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.nio.file.Files;
import java.util.Properties;
import org.junit.jupiter.api.BeforeEach;
@@ -27,6 +28,7 @@
import org.junit.jupiter.api.io.TempDir;
import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.io.ClassPathResource;
import org.springframework.mock.env.MockEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
@@ -74,42 +76,41 @@ void loadsPropertiesFromConfigFolderUsingProperties() throws Exception {
@Test
void loadsPropertiesFromConfigFolderUsingYml() throws Exception {
- Properties properties = new Properties();
- properties.put("abc", "def");
OutputStream out = new FileOutputStream(new File(this.configDir, "spring-boot-devtools.yml"));
- properties.store(out, null);
+ File file = new ClassPathResource("spring-devtools.yaml", getClass()).getFile();
+ byte[] content = Files.readAllBytes(file.toPath());
+ out.write(content);
out.close();
ConfigurableEnvironment environment = getPostProcessedEnvironment();
- assertThat(environment.getProperty("abc")).isEqualTo("def");
+ assertThat(environment.getProperty("abc.xyz")).isEqualTo("def");
}
@Test
void loadsPropertiesFromConfigFolderUsingYaml() throws Exception {
- Properties properties = new Properties();
- properties.put("abc", "def");
OutputStream out = new FileOutputStream(new File(this.configDir, "spring-boot-devtools.yaml"));
- properties.store(out, null);
+ File file = new ClassPathResource("spring-devtools.yaml", getClass()).getFile();
+ byte[] content = Files.readAllBytes(file.toPath());
+ out.write(content);
out.close();
ConfigurableEnvironment environment = getPostProcessedEnvironment();
- assertThat(environment.getProperty("abc")).isEqualTo("def");
+ assertThat(environment.getProperty("abc.xyz")).isEqualTo("def");
}
@Test
void loadFromConfigFolderWithPropertiesTakingPrecedence() throws Exception {
- Properties properties = new Properties();
- properties.put("abc", "def");
- properties.put("bar", "baz");
OutputStream out = new FileOutputStream(new File(this.configDir, "spring-boot-devtools.yaml"));
- properties.store(out, null);
+ File file = new ClassPathResource("spring-devtools.yaml", getClass()).getFile();
+ byte[] content = Files.readAllBytes(file.toPath());
+ out.write(content);
out.close();
Properties properties2 = new Properties();
- properties2.put("abc", "jkl");
+ properties2.put("abc.xyz", "jkl");
OutputStream out2 = new FileOutputStream(new File(this.configDir, "spring-boot-devtools.properties"));
properties2.store(out2, null);
out2.close();
ConfigurableEnvironment environment = getPostProcessedEnvironment();
- assertThat(environment.getProperty("abc")).isEqualTo("jkl");
- assertThat(environment.getProperty("bar")).isEqualTo("baz");
+ assertThat(environment.getProperty("abc.xyz")).isEqualTo("jkl");
+ assertThat(environment.getProperty("bing")).isEqualTo("blip");
}
@Test
@@ -131,16 +132,16 @@ void loadFromConfigFolderTakesPrecedenceOverHomeFolder() throws Exception {
@Test
void loadFromConfigFolderWithYamlTakesPrecedenceOverHomeFolder() throws Exception {
Properties properties = new Properties();
- properties.put("abc", "def");
+ properties.put("abc.xyz", "jkl");
properties.put("bar", "baz");
writeFile(properties, ".spring-boot-devtools.properties");
- Properties properties2 = new Properties();
- properties2.put("abc", "jkl");
OutputStream out2 = new FileOutputStream(new File(this.configDir, "spring-boot-devtools.yml"));
- properties2.store(out2, null);
+ File file = new ClassPathResource("spring-devtools.yaml", getClass()).getFile();
+ byte[] content = Files.readAllBytes(file.toPath());
+ out2.write(content);
out2.close();
ConfigurableEnvironment environment = getPostProcessedEnvironment();
- assertThat(environment.getProperty("abc")).isEqualTo("jkl");
+ assertThat(environment.getProperty("abc.xyz")).isEqualTo("def");
assertThat(environment.getProperty("bar")).isEqualTo(null);
}
diff --git a/spring-boot-project/spring-boot-devtools/src/test/resources/org/springframework/boot/devtools/env/spring-devtools.yaml b/spring-boot-project/spring-boot-devtools/src/test/resources/org/springframework/boot/devtools/env/spring-devtools.yaml
new file mode 100644
index 000000000000..80d448fbfef9
--- /dev/null
+++ b/spring-boot-project/spring-boot-devtools/src/test/resources/org/springframework/boot/devtools/env/spring-devtools.yaml
@@ -0,0 +1,3 @@
+abc:
+ xyz: def
+bing: blip
\ No newline at end of file