Home > Back-end >  how can application yaml value inject at runtime in spring boot?
how can application yaml value inject at runtime in spring boot?

Time:11-19

I want to change the value of application.yaml at loading time.

ex) application.yaml

user.name: ${name}

Here, I want to put this value by calling an external API such as a vault, rather than a program argument when the jar is executed with the name value.

First of all, I think I need to write code that implements EnvironmentPostProcessor and calls external API, but I don't know how to inject that value. can I get help?

public class EnvironmentConfig implements EnvironmentPostProcessor {

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment,
        SpringApplication application) {
        // API CAll
        
        // how can inject yaml value??
    }
}

I don't know which way to orient myself.

CodePudding user response:

OPTION 1: doing it via EnvironmentPostProcessor:

assuming you have registered you EnvironmentPostProcessor in /resources/META-INF/spring.factories file:

org.springframework.boot.env.EnvironmentPostProcessor=package.to.environment.config.EnvironmentConfig

all you need is to add your custom PropertySource:

public class EnvironmentConfig implements EnvironmentPostProcessor {

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment,
                                       SpringApplication application) {
        environment.getPropertySources()
                .addFirst(new CustomPropertySource("customPropertySource"));
    }
}

public class CustomPropertySource extends PropertySource<String> {
    public CustomPropertySource(String name) {
        super(name);
    }

    @Override
    public Object getProperty(String name) {
        if (name.equals("name")) {
            return "MY CUSTOM RUNTIME VALUE";
        }
        return null;
    }
}


OPTION 2: doing it via PropertySourcesPlaceholderConfigurer:

A class that is responsible for resolving these palceholders is a BeanPostProcessor called PropertySourcesPlaceholderConfigurer (see here).

So you could override it and provide you custom PropertySource that would resolve your needed property like so:

@Component
public class CustomConfigurer extends PropertySourcesPlaceholderConfigurer {

    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, ConfigurablePropertyResolver propertyResolver) throws BeansException {
        ((ConfigurableEnvironment) beanFactoryToProcess.getBean("environment"))
                .getPropertySources()
                .addFirst(new CustomPropertySource("customPropertySource"));
        super.processProperties(beanFactoryToProcess, propertyResolver);
    }
}

CodePudding user response:

use ConfigurationProperties for your properties and change it via an api like this:

@Component
@ConfigurationProperties(prefix = "user")
public class AppProperties {

    private String name;

    //getter and setter
}

@RestController
public class AppPropertiesController {
    @Autowire
    AppProperties prop;

    @PostMapping("/changeProp/{name}")
    public void change(@PathVariable String name){
        prop.setName(name);
    }
}
  • Related