Environment variables are a great way to configure Java applications without having to explicitly store settings in code, such as for database and caching servers, or for third-party APIs.
Keeping such settings outside of the code has several distinct advantages:
- Avoids the need to update and recompile code when settings change
- Helps prevent exposing sensitive credentials, such as usernames and passwords, and deployment tokens
- You can deploy the same code in multiple environments
In this short article, I'm going to show you some of the ways of working with environment variables in Java.
How to access environment variables in Java
One of the most common ways is to use System.getenv(), which accepts an optional String
argument. Based on whether a String
argument is passed, a different value is returned from the method. Specifically:
If a String
is passed and it matches a key in the internal environment Map
, then its value is returned. If a matching key is not found, null
is returned. If a String
argument is not passed, a read-only java.util.Map
containing all environment variables and their values is returned. The Map's keys are the environment variable names and its values are the values.
Keep in mind that different platforms operate in different ways, e.g., on UNIX, Linux, and macOS, environment variables are case-sensitive, whereas on Microsoft Windows they are not.
Below, you can see an example of how to use the method to retrieve the Linux SHELL
environment variable (which contains the user's shell).
package com.settermjd.twilio.envvars;
public class Main {
public static void main(String[] args) {
System.out.println(
String.format("The current shell is: %s.", System.getenv("SHELL"))
);
}
}
If you want to supply a default value, call System.genenv()
as follows:
System.getenv().getOrDefault("SHELL", "/bin/bash")
How to set environment variables
As well as reading environment variables, it's helpful to know how to set them. I won't go into too much detail, instead sticking to the essentials. However, if you'd like to learn about them in greater depth, Dominik Kundel has written a detailed blog post about them.
UNIX, Linux, and macOS
On UNIX, Linux, and macOS, environment variables can be set in three core ways.
Available to the current session and all child processes
You can initialise environment variables so that they're available to the current session, both the current one and any started in the current session, as well as any processes started in the current session, by using the builtin export command, as in the example below.
export USER_ID=1
Setting an environment variable this way isn't permanent. If you want to permanently set an environment variable, you need to set it in either the system-wide startup file, /etc/profile, or one of the user-specific startup files, i.e., ~/.bash_profile, ~/.bash_login, and ~/.profile.
Available to the current session
You can initialise an environment variable so that it's available to the current session but not any child processes, as in the example below, by not using the export
command.
USER_ID=1
Available to a specific process
Finally, you can initialise an environment variable so that it's available only to a specific process. This is helpful when only that process needs the variable. You initialise it as in the example below, when starting the desired process.
USER_ID=1 retrieveUserDetails
Microsoft Windows
Setting environment variables is a little different in Microsoft Windows. You can either set them via the Control Panel, or you can set them in the command prompt or PowerShell console. There are examples of the latter two below.
# Set USER_ID in the Windows Command Prompt
set USER_ID=1
# Set USER_ID in the Windows PowerShell console
$Env:USER_ID = 1
Using .env files
While setting environment variables this way can be very effective, it can also become cumbersome rather quickly. For example, by setting them in the operating system's shell, there is no concrete list of the variables which the application needs, nor is there information available about what a variable is for or what data type it must be.
Given that, among other reasons, The 12-Factor App recommended a strict separation of config from code. This practice quickly took hold throughout the developer community commonly through the use of .env (dotenv) files. These are plain text files that store a list of key/value pairs, defining the environment variables required for an application to work, as in the example below.
USER_ID=1
TWILIO_AUTH_TOKEN=1234567890987654321
To simplify getting started on a project, a further common practice emerged, that of including a .env.example file in a project which contains all of the keys—but without their values. When a new developer started working on the application, they would copy the file, naming it .env and set values for each key applicable to their local development environment.
Reading .env files
Assuming that the example above was the .env file for our project, we could use a package such as dotenv-java to make the variables available to our application.
If you're developing in Kotlin, you can use dotenv-kotlin.
You can see an example of using the package in the code example below.
package com.settermjd.twilio.envvars;
import io.github.cdimascio.dotenv.Dotenv;
import io.github.cdimascio.dotenv.DotenvException;
public class Main {
public static void main(String[] args) {
Dotenv dotenv = null;
dotenv = Dotenv.configure().load();
System.out.println(String.format(
"Hello World. Shell is: %s. Name is: %s",
System.getenv("SHELL"),
dotenv.get("NAME")
));
}
}
The code initialises a new Dotenv
object, dotenv, and calls Dotenv.configure().load()
to read in the environment variables in .env, located in the project's root directory. Following that, dotenv.get()
is used to retrieve the value of the String
object passed to it. If a matching key is not found, the method returns null
.
You can supply a default value as the second argument to the method if desired.
A note about .env file security
It's important to bear in mind that if sensitive data is stored in .env, that it must not be stored under version control. If that happens, then all of the security benefits of using dotenv files is lost. That's why it's common to exclude them from version control, such as by adding .env (and variations of the filename) to a project's .gitignore file when using Git.
That's how to work with environment variables in Java
I hope this article helped you understand how to use environment variables in your Java projects.
Do you have any other ways to work with environment variables? I’d love to know!
Matthew Setter is a PHP Editor in the Twilio Voices team and a polyglot developer. He’s also the author of Mezzio Essentials and Docker Essentials. When he’s not writing PHP code, he’s editing great PHP articles here at Twilio. You can find him at msetter@twilio.com; he's also settermjd on Twitter and GitHub.

Build an Interactive Voice Response (IVR) system and learn step-by-step call center creation by using Twilio, Java Servlets, and Gradle.

Learn how to create an engaging music trivia game for your festival group, bringing fun and entertainment to your gathering.

Learn about different ways to make HTTP requests, including updates for core libraries that developers still use for HTTP requests.

Learn how to access the most recent live news headlines from the US using Twilio SMS and News API.

Learn how to send bulk emails using Java Spring Boot and Twilio SendGrid API.

The differences between interfaces and abstract classes in Java using real-world applications from the JDK and common design patterns.