19

Spring Cloud Config Server accepts multiple profile and returns the properties for all the profiles when I access the /env endpoint of the application. The response lists the properties specific to each profile. If same property is present in 2 different property files , the one that is defined last takes precedence. Is there a way to get the final list of property key and values that will be used by the application?

Punter Vicky
  • 15,954
  • 56
  • 188
  • 315

4 Answers4

12

For Cloud Config Client Application

I've tried different ways and found the following (accidentally):

GET /env/.* returns full list of configuration properties

For Cloud Config Server Application

It turns out this is already implemented, but not documented well. All you need is to request json, yml or properties according to the patterns:

/{application}-{profile}.{ext}
/{label}/{application}-{profile}.{ext}
Vyacheslav Shvets
  • 1,735
  • 14
  • 23
  • To add here, it is possible to add a prefix to all Spring Config Server built-in endpoints using property `management.context-path` in the config server configuration file. So if you see that built-in endpoints do not work, check your properties to find a value for that property. If it is set, then use `GET /prefixValue/env` instead of just `GET /env` – user07 Jul 24 '20 at 20:20
  • Not "env" it's a variable. In my case it's `GET /*` – Philip Rego Jan 01 '21 at 19:34
  • thank you, i've finally got all the configs – Maks Chornyi Mar 02 '23 at 16:46
9
import java.util.properties;

import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.Environment;

public class MyClass {
  @Autowired
  private Environment    env;

  Properties getProperties() {
    Properties props = new Properties();
    CompositePropertySource bootstrapProperties = (CompositePropertySource)  ((AbstractEnvironment) env).getPropertySources().get("bootstrapProperties");
    for (String propertyName : bootstrapProperties.getPropertyNames()) {
      props.put(propertyName, bootstrapProperties.getProperty(propertyName));
    }

    return props;
  }

}

Sorry... this is my first time answering a question here. I created an account specifically to answer this question because I came upon it while researching the same issue. I found a solution that worked for me and decided to share it.

Here goes my explanation of what was done:

  1. I initialize a new "Properties" object (could be a HashMap or whatever else you want)

  2. I lookup the property source for the "bootstrapProperties" which is a CompositePropertySource object. This property source contains all of the application properties that were loaded.

  3. I loop through all the property names returned from the "getPropertyNames" method on the CompositePropertySource object and create a new property entry.

  4. I return the properties object.

Todd Jones
  • 141
  • 3
4

This seems to be an intentional limitation of the Spring Framework.

See here

You could hack it and inject the PropertySources interface, then loop over all the individual PropertySource objects, but you'd have to know what properties you're looking for.

dardo
  • 4,870
  • 4
  • 35
  • 52
  • You had the original idea implemented by todd-jones and sudhakar, so special THANKS to you! – t0r0X May 08 '20 at 10:24
3
  1. Externalized Configuration

Spring Boot allows you to externalize your configuration so you can work with the same application code in different environments. You can use properties files, YAML files, environment variables and command-line arguments to externalize configuration. Property values can be injected directly into your beans using the @Value annotation, accessed via Spring’s Environment abstraction or bound to structured objects via @ConfigurationProperties.

Spring Boot uses a very particular PropertySource order that is designed to allow sensible overriding of values. Properties are considered in the following order:

  • Devtools global settings properties on your home directory (~/.spring-boot-devtools.properties when devtools is active).
  • @TestPropertySource annotations on your tests.
  • @SpringBootTest#properties annotation attribute on your tests.
  • Command line arguments.
  • Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property)
  • ServletConfig init parameters.
  • ServletContext init parameters.
  • JNDI attributes from java:comp/env.
  • Java System properties (System.getProperties()).
  • OS environment variables.
  • A RandomValuePropertySource that only has properties in random.*.
  • Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants)
  • Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants)
  • Application properties outside of your packaged jar (application.properties and YAML variants).
  • Application properties packaged inside your jar (application.properties and YAML variants).
  • @PropertySource annotations on your @Configuration classes.
  • Default properties (specified using SpringApplication.setDefaultProperties).

The below program prints properties from spring boot environment.

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.StandardServletEnvironment;

@Component
public class EnvironmentLogger extends ApplicationObjectSupport {

    @Override
    protected void initApplicationContext(ApplicationContext context) throws BeansException {
        Environment environment = context.getEnvironment();
        String[] profiles = environment.getActiveProfiles();
        if(profiles != null && profiles.length > 0) {
            for (String profile : profiles) {
               System.out.print(profile);
            }           
        } else {
            System.out.println("Setting default profile");
        }

        //Print the profile properties
        if(environment != null && environment instanceof StandardServletEnvironment) {
            StandardServletEnvironment env = (StandardServletEnvironment)environment;
            MutablePropertySources mutablePropertySources = env.getPropertySources();
            if(mutablePropertySources != null) {
                for (PropertySource<?> propertySource : mutablePropertySources) {
                    if(propertySource instanceof MapPropertySource) {
                        MapPropertySource mapPropertySource = (MapPropertySource)propertySource;
                        if(mapPropertySource.getPropertyNames() != null) {
                            System.out.println(propertySource.getName());
                            String[] propertyNames = mapPropertySource.getPropertyNames();
                            for (String propertyName : propertyNames) {
                                Object val = mapPropertySource.getProperty(propertyName);
                                System.out.print(propertyName);
                                System.out.print(" = " + val);
                            }
                        }
                    }
                }
            }
        }
    }
}
Sudhakar
  • 3,104
  • 2
  • 27
  • 36