Can Key value pairs in application.properties be considered as environmental variables?

6/10/2019

New to spring boot.

While exploring spring boot env variables, came to know that, env variables can be accessed by ${KeyName} from code.

Got a question like,

Case 1: In @Configuration files, we are accessing keys in application.properties using @Value(value = "${KeyName}"). So, we are using almost same syntax for accessing env variables and accessing keys in application.properties.

Case 2: When trying to access the keys in application.properties using system.getEnv("keyname"), I got only null.

Case 3: Recently worked on configmap in kubernetes with spring boot.

Config file looks like,

spec:
  containers:
  - name: demo-configconsumercontainer
    image: springbootappimage:latest
    ports:
    - containerPort: 8080
    envFrom:
      - configMapRef:
          name: example-configmap

All the values from configMap is exported as environmental variables and I am accessing those values by @Value(value = "${KeyName}") and by system.getEnv(KeyName).

  1. My question is, how case 3 is working when case 2 is not.
  2. Is Spring boot made such a way that, it is allowing to access by ${KeyName} and not by system.getEnv(KeyName)? (ie. Case 2)

Could some one clarify my questions here.

-- NANDAKUMAR
application.properties
configmap
environment-variables
kubernetes
spring-boot

2 Answers

6/10/2019

Using @Value annotation, you can access a property from many property sources such as in application.properties or an environment variable and few more property sources.

The important point here is ordering of these property sources.

Below is the order of looking up the property in various sources.

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

In your case, the property is either declared in environment variable or in application.yaml and hence accessible using @Value annotation.

-- Shailesh Pratapwar
Source: StackOverflow

6/10/2019

See the Spring docs:

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

Spring includes environment variables as a potential property source, but does not export its properties defined in other ways as environment variables. So it isn't a two way street, which is why case #2 does not work.

Case #3 is a separate reality, just the fact that when K8s runs a container defined in this way with env vars, it makes those vars available in the container environment. Any software system or programming language able to read environment variables will be able to refer to those variables, including Java code. This has nothing to do specifically with Java or Spring...it's just another way to inject environment variables into the runtime environment.

UPDATE: I didn't see @ShaileshPratapwar's answer until I posted my own. Seems our answers are roughly the same, although I think it's good that you know where the list of property sources, and their order of priority, comes from. It's very clearly defined by the Spring docs.

-- Steve
Source: StackOverflow