I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE COURSE

1. Introduction

The package java.lang is automatically imported when in a Java application. This package contains many commonly used classes from NullPointerException to Object, Math, and String.

The java.lang.System class is a final class, meaning that we cannot create an instance of it, therefore all methods are static.

We are going to look at the differences between two System methods for reading system properties and environment variables.

These methods are getProperty and getenv.

2. Using System.getProperty()

The Java platform uses a Properties object to provide information about the local system and configuration and we call it System Properties.

System Properties include information such as the current user, the current version of the Java runtime, and file path-name separator.

In the below code, we use System.getProperty(“log_dir”) to read the value of the property log_dir. We also make use of the default value parameter so if the property does not exist, getProperty returns of /tmp/log:

String log_dir = System.getProperty("log_dir","/tmp/log");

To update System Properties at runtime, use the method System.setProperty method:

System.setProperty("log_dir", "/tmp/log");

We can pass our own properties or configurations values to the application using the propertyName command line argument in the format:

java -jar jarName -DpropertyName=value

Setting the property of foo with a value of bar in app.jar:

java -jar app -Dfoo=”bar”

System.getProperty will always return a String.

3. Using System.getenv()

Environment Variables are key/value pairs like Properties. Many Operating Systems use Environment Variables to allow configuration information to be passed into applications.

The way to set an environment variable differs from one operating system to another. For example, in Windows, we use a System Utility application from the control panel while in Unix we use shell scripts.

When creating a process, by default it inherits a clone environment of its parent process.

The following code snippet shows using a lambda expression to print all Environment Variables.

System.getenv().forEach((k, v) -> {
    System.out.println(k + ":" + v);
});

getenv() returns a read-only Map. Trying to add values to the map throws an UnsupportedOperationException.

To obtain a single variable, call getenv with the variable name:

String log_dir = System.getenv("log_dir");

On the other hand, we can create another process from our application and add new variables to its environment.

To create a new process in Java, we use ProcessBuilder class which has a method called environment. This method returns a Map but this time the map is not read-only, meaning we can add elements to it:

ProcessBuilder pb = new ProcessBuilder(args);
Map<String, String> env = pb.environment();
env.put("log_dir", "/tmp/log");
Process process = pb.start();

4. The Differences

Although both are essentially maps that provide String values for String keys, let’s look at a few differences:

  1. We can update Properties at runtime while Environment Variables are an immutable copy of the Operating System’s variables.
  2. Properties are contained only within Java platform while Environment Variables are global at the Operating System level – available to all applications running on the same machine.
  3. Properties must exist when packaging the application but we can create Environment Variables on the Operating System at almost any point.

5. Conclusion

Although conceptually similar, the application of both Properties and Environment Variables are quite different.

The choice between the options is often a question of scope. Using Environment Variables, the same application can be deployed to multiple machines to run different instances and can be configured at the Operating System level or even in AWS or Azure Consoles. Removing the needing to rebuild application to update config.

Always remember that getProperty follows camel-case convention and getenv does not.

I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE LESSONS