I'm currently learning how to work with Spring Boot. Until now I never used Frameworks like Spring and used files directly (FileInputStream, etc.)
So here is the case: I have some dynamic configuration values like OAuth tokens. I want to use them inside of my application but I have no clue how to realize this with Spring.
Here is some code to make clear what I'm searching 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();
}
}
Sure, this example is very plain. Here I want to get the value "token" dynamically from a YAML configuration file. This file must be accessible for the user 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 I have now idea how to apply this to my project.
How can I achive 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 (Located in 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
First of all your Test
class should be annotated with @Component
in order for it to be registered as a bean by spring (also make sure all your classes are under your main package - the main package is where a class that is annotated with @SpringBootApplication
reside).
Now you should either move all your properties to application.yml
(src/main/resources/application.yml
), that is picked automatically by spring boot (note that it should be .yml
instead of .yaml
or register a custom 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;
}
Now your properties should be loaded to spring's environment and they will be available for injection with @Value
to your beans.
You basically got three easy options.
application.properties
which is Springs internal configuration file.--spring.config.name
as VM parameter.@PropertySource
to load either an internal or external configuration. @PropertySource
only works with .properties config files. There is currently an open Jira ticket to implement yaml support. You can follow the progress here: https://jira.spring.io/browse/SPR-13912
Notice, if you are using multiple yaml and/or properties files which contain common keys, the it will always use the definition of the key which was loaded last. This is why the below example uses two different keys. If it used the same key, then it would print out PROPERTIES FILE
twice.
Short simple code snippet:
@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
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);
}
}
Properties and Yaml files
Both of these files are located in src/main/resources
watchdog.yml:
watchdog:
token: YAML FILE
watchdog.properties:
watchdog.prop.token=PROPERTIES FILE
Output
PROPERTIES FILE
YAML FILE
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With