Last active
July 9, 2020 03:34
-
-
Save djkeh/53309cda4437a3fb269cb19f8141839a to your computer and use it in GitHub Desktop.
Sample codes of reading user-custom yaml files as ConfigurationProperties of Spring Boot.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.your.project.config; | |
import com.zaxxer.hikari.HikariDataSource; | |
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; | |
import org.springframework.boot.context.properties.ConfigurationProperties; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import org.springframework.context.annotation.Primary; | |
import javax.sql.DataSource; | |
/** | |
* Sample bean config to show how to apply custom yaml properties | |
* | |
* @author Uno Kim | |
*/ | |
@Configuration | |
public class DataSourceConfig { | |
@Bean | |
@Primary | |
@ConfigurationProperties("datasource.mydb") | |
public DataSourceProperties mydbDataSourceProperties() { | |
return new DataSourceProperties(); | |
} | |
@Bean | |
@Primary | |
@ConfigurationProperties("datasource.mydb.configuration") | |
public DataSource mydbDataSource(DataSourceProperties mydbDataSourceProperties) { | |
return mydbDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
spring.profiles: test | |
datasource: | |
mydb: | |
username: me | |
password: whoelsecoulditbe | |
url: jdbc:mysql://locahost:3306/mydb | |
configuration: | |
dataSourceProperties: | |
databaseName: mydb | |
serverName: locahost | |
portNumber: 3306 | |
yourdb: | |
username: you | |
password: whocares | |
url: jdbc:mysql://1.2.3.4:3307/yourdb | |
configuration: | |
dataSourceProperties: | |
databaseName: yourdb | |
serverName: 1.2.3.4 | |
portNumber: 3307 | |
--- | |
spring.profiles: alpha | |
datasource: | |
mydb: | |
username: me | |
password: whoelsecoulditbe | |
url: jdbc:mysql://alpha.my-server.com:3306/mydb | |
configuration: | |
dataSourceProperties: | |
databaseName: mydb | |
serverName: alpha.my-server.com | |
portNumber: 3306 | |
yourdb: | |
username: you | |
password: whocares | |
url: jdbc:mysql://alpha.your-server.com:3307/yourdb | |
configuration: | |
dataSourceProperties: | |
databaseName: yourdb | |
serverName: alpha.your-server.com | |
portNumber: 3307 | |
--- | |
spring.profiles: sandbox | |
datasource: | |
mydb: | |
username: me | |
password: whoelsecoulditbe | |
url: jdbc:mysql://sandbox.my-server.com:3306/mydb | |
configuration: | |
dataSourceProperties: | |
databaseName: mydb | |
serverName: sandbox.my-server.com | |
portNumber: 3306 | |
yourdb: | |
username: you | |
password: whocares | |
url: jdbc:mysql://sandbox.your-server.com:3307/yourdb | |
configuration: | |
dataSourceProperties: | |
databaseName: yourdb | |
serverName: sandbox.your-server.com | |
portNumber: 3307 | |
--- | |
spring.profiles: beta,real | |
datasource: | |
mydb: | |
username: me | |
password: thisisveryseriouspassword123 | |
url: jdbc:mysql://my-server.com:3306/mydb | |
configuration: | |
dataSourceProperties: | |
databaseName: mydb | |
serverName: my-server.com | |
portNumber: 3306 | |
yourdb: | |
username: you | |
password: ohdidyoucare? | |
url: jdbc:mysql://your-server.com:3307/yourdb | |
configuration: | |
dataSourceProperties: | |
databaseName: yourdb | |
serverName: your-server.com | |
portNumber: 3307 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
org.springframework.boot.env.EnvironmentPostProcessor=com.your.project.config.YamlEnvironmentPostProcessor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.your.project.config; | |
import org.springframework.boot.SpringApplication; | |
import org.springframework.boot.env.EnvironmentPostProcessor; | |
import org.springframework.boot.env.YamlPropertySourceLoader; | |
import org.springframework.core.env.ConfigurableEnvironment; | |
import org.springframework.core.env.PropertySource; | |
import org.springframework.core.io.ClassPathResource; | |
import org.springframework.core.io.Resource; | |
import java.io.IOException; | |
import java.util.List; | |
import java.util.Optional; | |
import java.util.stream.Stream; | |
/** | |
* <p> | |
* Spring-Boot-Guided customization to read user-defined properties from yaml files. | |
* This supports multiple profiles per single file. | |
* It could be useful if you'd like to separate some extra information from single `application.yml`. | |
* Automatic yaml file scanning isn't implemented here, so you have to write filenames in this class manually. | |
* | |
* <p> | |
* Differences between processing `application.yml`: | |
* | |
* <ul> | |
* <li> | |
* Unlike how Spring Boot treats `application.yml`, This code doesn't implement global profile. | |
* Each document of profile in a yaml file serves its own properties only. | |
* If you write a document which doesn't have `spring.profiles`, it's not a global profile and is simply ignored. | |
* The only chance the yaml document without `spring.profiles` can be read is that | |
* the document is written in top position and the input profile doesn't match any of documents in yaml file. | |
* This still doesn't mean the document acted as a global profile. | |
* This characteristics can be handy if you have single document in a yaml file. | |
* You just don't have to specify the `spring.profiles`, | |
* as {@link #loadYaml(Resource, ConfigurableEnvironment)} would read it anyway. | |
* </li> | |
* <li> | |
* The property name `spring.profiles` for recognizing profiles in custom yaml file has nothing to do with | |
* the real Spring Boot property `spring.profiles`. I named it for better understanding and consistency. | |
* The name is used for identifying profiles only in custom yaml files, | |
* and you can change it to any name you want. | |
* </li> | |
* </ul> | |
* | |
* @author Uno Kim | |
* @see <a href="https://docs.spring.io/spring-boot/docs/2.3.1.RELEASE/reference/htmlsingle/#howto-customize-the-environment-or-application-context">Reference doc.</a> | |
*/ | |
public class YamlEnvironmentPostProcessor implements EnvironmentPostProcessor { | |
private static final List<String> CLASSPATH_FILES = List.of("sample.yml"); // Additional yaml files you want to read are indicated here. | |
private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); | |
@Override | |
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { | |
CLASSPATH_FILES.forEach(filename -> { | |
Resource path = new ClassPathResource(filename); | |
PropertySource<?> propertySource = loadYaml(path, environment); | |
environment.getPropertySources().addLast(propertySource); | |
}); | |
} | |
private PropertySource<?> loadYaml(Resource path, ConfigurableEnvironment environment) { | |
if (!path.exists()) { | |
throw new IllegalArgumentException("Resource " + path + " does not exist"); | |
} | |
try { | |
List<PropertySource<?>> propertySources = this.loader.load(path.getFilename(), path); | |
Optional<PropertySource<?>> propertySource = propertySources.stream() | |
.filter(loadedFile -> { | |
String foundProperty = (String) loadedFile.getProperty("spring.profiles"); // The property name to recognize multiple profiles in single yaml file | |
if (foundProperty == null) { | |
return false; | |
} | |
List<String> profiles = List.of(foundProperty.split(",")); | |
return Stream.of(environment.getActiveProfiles()) | |
.anyMatch(profiles::contains); | |
}) | |
.findFirst(); | |
return propertySource.orElse(propertySources.get(0)); // orElse() tries to read a top document from a yaml file in case the user gave wrong spring profiles. | |
} | |
catch (IOException ex) { | |
throw new IllegalStateException("Failed to load yaml configuration from " + path, ex); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment