简体   繁体   中英

List distributed properties in Spring Boot

Code sample below is from a Spring Boot application that obtains property definitions from the local application.properties file. Additional or overriding property definitions are obtained from a remote Consul server. The goal is to have the application enumerate all property definitions regardless of the source. Example setup:

The local application.properties file contains this property definition spring.cloud.stream.bindings.breakoutOutputChannel.destination=breakout_topic_local

The overriding definition for the same property in the Consul server is: spring.cloud.stream.bindings.breakoutOutputChannel.destination=breakout_topic_production

In the same code I am using two mechanisms to access the same property value. First is use of the @Value annotation, the second is querying properties obtained from the environment. The means of obtaining the applications enviroment properties is also show below.

When using the @Value annotation the proper override value is obtained. But when accessing the property definition directly only the value from the local file is available. Example show below.

Is it possible to obtain the same Map of properties that the @Value annotation uses so that its contents can be enumerated?

Sample code:

    @Value("${spring.cloud.stream.bindings.breakoutOutputChannel.destination}")
    String breakout;
    
    @EventListener
    public void onApplicationEvent(ApplicationReadyEvent  event) {
         Properties props =applicationProperties(event.getApplicationContext().getEnvironment());
         log.info("Property spring.cloud.stream.bindings.breakoutOutputChannel.destination");
         log.info( " value from bound var = " +breakout);
         log.info( " value from properties = " +props.getProperty("spring.cloud.stream.bindings.breakoutOutputChannel.destination"));
    }
    
    public Properties applicationProperties(Environment env) {
        final Properties properties = new Properties();
        for(Iterator it = ((AbstractEnvironment) env).getPropertySources().iterator(); it.hasNext(); ) {
            PropertySource propertySource = (PropertySource) it.next();
            if (propertySource instanceof PropertiesPropertySource) {
                log.info("Adding all properties contained in " + propertySource.getName());
                properties.putAll(((MapPropertySource) propertySource).getSource());
            }
            if (propertySource instanceof  CompositePropertySource){
                properties.putAll(getPropertiesInCompositePropertySource((CompositePropertySource) propertySource));
            }
        }
        return properties;
    }

    private Properties getPropertiesInCompositePropertySource(CompositePropertySource compositePropertySource){
        final Properties properties = new Properties();
        compositePropertySource.getPropertySources().forEach(propertySource -> {
            if (propertySource instanceof MapPropertySource) {
                log.info("Adding all properties contained in " + propertySource.getName());
                properties.putAll(((MapPropertySource) propertySource).getSource());
            }
            if (propertySource instanceof CompositePropertySource)
                properties.putAll(getPropertiesInCompositePropertySource((CompositePropertySource) propertySource));
        });
        return properties;
    }

Sample output

Adding all properties contained in applicationConfig: [file:./application.properties]
Adding all properties contained in applicationConfig: [classpath:/application.properties]
Property spring.cloud.stream.bindings.breakoutOutputChannel.destination
 value from bound var = breakout_topic_production
 value from properties = breakout_topic_local

While the generated properties object, created in the above example, source is the application Environment, the values are indeed only those that are included in the local property definition files.

However if the property key is used to get the value directly from the Environment, the the value returned will contain any override distributed to the application from Consul. From the example the return value from

event.getApplicationContext().getEnvironment().getProperty("spring.cloud.stream.bindings.breakoutOutputChannel.destination"));

will return the correct property value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM