How do I load external config using Spring Boot?
I am currently learning how to work with Spring Boot. Until now I have never used Frameworks like Spring and used files directly (FileInputStream, etc.)
So like this: I have some dynamic config values ββlike OAuth tokens. I want to use them inside my application, but I don't know how to implement this with Spring.
Here are some codes to clearly define what I am looking for:
@Config("app.yaml")
public class Test {
@Value("app.token")
private String token;
private IClient client;
public Test(String token) {
this.client = ClientFactory.build(token).login();
}
}
Of course, this example is very simple. Here I want to dynamically get the "token" value from the YAML config file. This file must be user accessible and not included in the JAR file.
I also found that doc: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html , but now I have an idea how to apply this to to my project.
How can I achieve this? Thank you in advance:)
Edit:
Here are some parts of my code:
WatchdogBootstrap.java
package de.onkelmorph.watchdog;
import org.springframework.boot.Banner.Mode;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource("classpath:Beans.xml")
public class WatchdogBootstrap {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(WatchdogBeans.class);
app.setBannerMode(Mode.OFF);
app.setWebEnvironment(false);
app.run(args);
}
}
Beans.xml (found in the default package)
<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config></context:annotation-config>
</beans>
Watchdog.java
package de.onkelmorph.watchdog;
// Imports ...
@Component
@PropertySource("file:/watchdog.yml")
public class Watchdog {
// ...
// Configuration
@Value("${watchdog.token}")
private String token;
public Watchdog() {
System.out.println(this.token);
System.exit(0);
}
// ...
}
watchdog.yml (located in src / main / resources)
watchdog:
token: fghaepoghaporghaerg
source to share
First of all, your class Test
must be annotated with @Component
so that it is registered as a bean on spring (also make sure all your classes are under your main package - the main package is where the class annotated with @SpringBootApplication
is located).
Now you have to either move all your properties to application.yml
( src/main/resources/application.yml
), which is automatically selected on spring boot (note that this should be .yml
instead .yaml
), or register a custom one PropertySourcesPlaceholderConfigurer
.
Example for PropertySourcesPlaceholderConfigurer
:
@Bean
public static PropertySourcesPlaceholderConfigurer PropertySourcesPlaceholderConfigurer() throws IOException {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
MutablePropertySources propertySources = new MutablePropertySources();
Resource resource = new DefaultResourceLoader().getResource("classpath:application.yml");
YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader();
PropertySource<?> yamlProperties = sourceLoader.load("yamlProperties", resource, null);
propertySources.addFirst(yamlProperties);
configurer.setPropertySources(propertySources);
return configurer;
}
Your properties should now be loaded into the spring environment and they will be available for insertion from @Value
to your beans.
source to share
Basically, you have three simple options.
- Use
application.properties
that is Springs internal config file. - Load your own config file using
--spring.config.name
VM as parameter. - You can use
@PropertySource
to load internal or external configuration.@PropertySource
only works with config files .properties. There is currently a Jira open ticket to implement yaml support. You can follow the progress here: https://jira.spring.io/browse/SPR-13912
Note that if you use multiple yaml files and / or properties that contain shared keys, it will always use the definition of the key that was last loaded. This is why the example below uses two different keys. If he used the same key, he printed twice PROPERTIES FILE
.
A short, simple piece of code:
@Component
@PropertySource("file:/path/to/config/app.properties")
class Address{
@Value("${addr.street}")
private String street;
@Value("${addr.city}")
private String city;
}
app.properties
addr.street=Abbey Road
addr.city=London
An extensive example
DemoApplication.java
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
//Call class with properties
context.getBean(WatchdogProperties.class).test();
//Call class with yaml
context.getBean(WatchdogYaml.class).test();
}
//Define configuration file for yaml
@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("watchdog.yml"));
propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
return propertySourcesPlaceholderConfigurer;
}
}
WatchdogProperties.java
@Component
//PropertySource only works for .properties files
@PropertySource("classpath:watchdog.properties")
public class WatchdogProperties{
//Notice the key name is not the same as the yaml key
@Value("${watchdog.prop.token}")
private String token;
public void test(){
System.out.println(token);
}
}
WatchdogYaml.java
@Component
class WatchdogYaml{
//Notice the key name is not the same as the properties key
@Value("${watchdog.token}")
private String token;
public void test(){
System.out.println(token);
}
}
Yaml properties and files
Both of these files are located insrc/main/resources
watchdog.yml:
watchdog:
token: YAML FILE
watchdog.properties:
watchdog.prop.token=PROPERTIES FILE
Output
PROPERTIES FILE
YAML FILE
source to share