A no-dependency, pure Java port of the Ruby dotenv project. Load environment variables from a .env
file.
dotenv-java also powers the popular dotenv-kotlin library.
Why dotenv?
Storing configuration in the environment is one of the tenets of a twelve-factor app. Anything that is likely to change between deployment environmentsβsuch as resource handles for databases or credentials for external servicesβshould be extracted from the code into environment variables.
But it is not always practical to set environment variables on development machines or continuous integration servers where multiple projects are run. Dotenv load variables from a .env file into ENV when the environment is bootstrapped.
Environment variables listed in the host environment override those in .env
.
Use dotenv.get("...")
instead of Java's System.getenv(...)
.
Requires Java 11 or greater.
Still using Java 8? Use version 2.3.2
<dependency>
<groupId>io.github.cdimascio</groupId>
<artifactId>dotenv-java</artifactId>
<version>3.1.0</version>
</dependency>
compile 'io.github.cdimascio:dotenv-java:3.1.0'
implementation 'io.github.cdimascio:dotenv-java:3.1.0'
implementation("io.github.cdimascio:dotenv-java:3.1.0")
Looking for the Kotlin variant? get dotenv-kotlin.
Use dotenv.get("...")
instead of Java's System.getenv(...)
. Here's why.
Create a .env
file in the root of your project
# formatted as key=value
MY_ENV_VAR1=some_value
MY_EVV_VAR2=some_value #some value comment
MULTI_LINE="some
multi line
value"
Dotenv dotenv = Dotenv.load();
dotenv.get("MY_ENV_VAR1")
-
Create an assets folder
-
Add
env
(no dot) to the assets folder -
Configure dotenv to search
/assets
for a file with nameenv
Dotenv dotenv = Dotenv.configure() .directory("/assets") .filename("env") // instead of '.env', use 'env' .load(); dotenv.get("MY_ENV_VAR1");
Note: The above configuration is required because dot files in /assets
do not appear to resolve on Android. (Seeking recommendations from the Android community on how dotenv-java
configuration should work in order to provide the best experience for Android developers)
Alternatively, if you are using Provider android.resource
you may specify
.directory("android.resource://com.example.dimascio.myapp/raw")
Configure dotenv-java
once in your application.
Dotenv dotenv = Dotenv.configure()
.directory("./some/path")
.ignoreIfMalformed()
.ignoreIfMissing()
.load();
Note, environment variables specified in the host environment take precedence over those in .env
.
dotenv.get("HOME");
dotenv.get("MY_ENV_VAR1", "default value");
Note, environment variables specified in the host environment take precedence over those in .env
.
for (DotenvEntry e : dotenv.entries()) {
System.out.println(e.getKey());
System.out.println(e.getValue());
}
-
path
specifies the directory containing.env
. Dotenv first searches for.env
using the given path on the filesystem. If not found, it searches the given path on the classpath. Ifdirectory
is not specified it defaults to searching the current working directory on the filesystem. If not found, it searches the current directory on the classpath.example
Dotenv .configure() .directory("/some/path") .load();
-
Use a filename other than
.env
. Recommended for use with Android (see details)example
Dotenv .configure() .filename("myenv") .load();
-
Do not throw when
.env
entries are malformed. Malformed entries are skipped.example
Dotenv .configure() .ignoreIfMalformed() .load();
-
Do not throw when
.env
does not exist. Dotenv will continue to retrieve environment variables that are set in the environment e.g.dotenv["HOME"]
example
Dotenv .configure() .ignoreIfMissing() .load();
-
Load environment variables into System properties, thus making all environment variables accessible via
System.getProperty(...)
example
Dotenv .configure() .systemProperties() .load();
- with Maven (simple)
- see Java tests
- spring-dotenv - dotenv-java as a Spring PropertySource
- dotenv-kotlin - a Kotlin DSL for dotenv-java
see javadoc
Q: Should I deploy a .env
to e.g. production?
A: Tenant III of the 12 factor app methodology states "The twelve-factor app stores config in environment variables". Thus, it is not recommended to provide the .env file to such environments. dotenv, however, is super useful in e.g a local development environment as it enables a developer to manage the environment via a file which is more convenient.
Using dotenv in production would be cheating. This type of usage, however is an anti-pattern.
Q: Why should I use dotenv.get("MY_ENV_VAR")
instead of System.getenv("MY_ENV_VAR")
A: Since Java does not provide a way to set environment variables on a currently running process, vars listed in .env
cannot be set and thus cannot be retrieved using System.getenv(...)
.
Q: Can I use System.getProperty(...)
to retrieve environment variables?
A: Sure. Use the systemProperties
option. Or after initializing dotenv set each env var into system properties manually. For example:
example
Dotenv dotenv = Dotenv.configure().load();
dotenv.entries().forEach(e -> System.setProperty(e.getKey(), e.getValue()));
System.getProperty("MY_VAR");
Q: Should I have multiple .env files?
A: No. We strongly recommend against having a "main" .env file and an "environment" .env file like .env.test. Your config should vary between deploys, and you should not be sharing values between environments.
In a twelve-factor app, env vars are granular controls, each fully orthogonal to other env vars. They are never grouped together as βenvironmentsβ, but instead are independently managed for each deploy. This is a model that scales up smoothly as the app naturally expands into more deploys over its lifetime.
β The Twelve-Factor App
Q: Should I commit my .env
file?
A: No. We strongly recommend against committing your .env
file to version control. It should only include environment-specific values such as database passwords or API keys. Your production database should have a different password than your development database.
Q: What happens to environment variables that were already set?
A: dotenv-java will never modify any environment variables that have already been set. In particular, if there is a variable in your .env
file which collides with one that already exists in your environment, then that variable will be skipped. This behavior allows you to override all .env
configurations with a machine-specific environment, although it is not recommended.
Q: What about variable expansion in .env
?
A: We haven't been presented with a compelling use case for expanding variables and believe it leads to env vars that are not "fully orthogonal" as The Twelve-Factor App outlines. Please open an issue if you have a compelling use case.
Q: Can I supply a multi-line value?
A: dotenv-java exhibits the same behavior as Java's System.getenv(...)
, thus if a multi-line value is needed you might consider encoding it via e.g. Base64. see this comment for details.
Note and reference: The FAQs present on motdotla's dotenv node project page are so well done that I've included those that are relevant in the FAQs above.
see CONTRIBUTING.md
see LICENSE (Apache 2.0)
Thanks goes to these wonderful people (emoji key):
Clement Cherlin π» |
Alex Braga π |
Alexey Venderov π» |
yassenb π» |
Sidney Beekhoven π» π |
Manoel Campos π» |
This project follows the all-contributors specification. Contributions of any kind welcome!