Skip to content
This repository has been archived by the owner on Jan 6, 2023. It is now read-only.

Latest commit

 

History

History
179 lines (144 loc) · 6.12 KB

README.md

File metadata and controls

179 lines (144 loc) · 6.12 KB

Warning

This is no longer being maintained due to a newer version being available with improved features. You can still use this with no issues for as long as Java allows, but we recommend using the newer one especially for Kotlin developers.

https://github.com/ShindouMihou/envi

🎉 Dotenv

A simple, dependency-free dotenv serialization and deserialization for Java that is able to use reflection to fill in variables for you.

📦 What makes this different from the other Dotenv library?

This dotenv library utilizes Reflection to automatically fill in variables to your specific class similar to how GSON can deserialize a JSON into an Object, this does the same but only works for static variables as our thought process is that .env is most likely used for configuration and this usually means the variables are usually static (also code limitations).

🍰 Installation

You can easily install this library from Central Maven:

Maven

<dependency>
  <groupId>pw.mihou</groupId>
  <artifactId>Dotenv</artifactId>
  <version>1.0.1</version>
</dependency>

Gradle

implementation 'pw.mihou:Dotenv:1.0.1'

💬 How to use this?

To use this library, you have to understand the two types of Dotenv parsers that exists here (Normal and Reflective), both have pretty much the same methods as Reflective extends over Normal allowing it to have the same methods as Normal but compared to Normal, it has methods like reflectTo(...) and create(...) which utilizes Reflection to reflect variables onto their part and also to create a .env from an Object.

If you want to use the normal parser, you can simply create a new instance through:

NormalDotEnv dotEnv = Dotenv.as();

The .as() loads the default settings which are:

  • It loads the environments from the .env file located on the ROOT-LEVEL of the directory.
  • It does not fallback to the System Environmental Variables if a variable is not there on .env.

You can customize it to support them through the methods:

NormalDotEnv dotEnv = Dotenv.as(new File("/path/to/someEnvFile.env"), true);

To make a Reflective Dotenv, you can easily cast over NormalDotEnv as internally, they are both the same or you could create a new Dotenv instance the proper way, for example:

ReflectiveDotenv dotEnv = Dotenv.asReflective();

The same methods and rules applies to the above, after creating the instance, all the variables inside the .env should have been loaded into the Dotenv instance which allows you to retrieve them through the method:

String value = dotEnv.get("someKey");

✨ Deserializing with Reflective.

If you don't want to spend a pile load of time adding a method that parses and sets the variables onto a Class, then feel free to use ReflectiveDotEnv which is what we recommend to use over NormalDotenv and also is what makes this library different from others. You can easily set this up by simply doing:

dotEnv.reflectTo(SomeConfiguration.class);

By default, the reflector can parse the following types: character, long, integer, string, boolean, double but you can make your own ReflectiveAdapter to parse your own entity, for example:

SomeEntity.class

class SomeEntity {
  
  public String response;
  
  public SomeEntity(String keyA, String keyB) {
    this.response = keyB + " " + keyA;
  }

}

If we want the reflective dotenv to be able to parse the value into that field, then all we have to do is add a ReflectiveAdapter:

SomeEntityAdapter.class

class SomeEntityAdapter implements ReflectiveAdapter<SomeEntity> {

  public SomeEntity parse(String value, Map<String, String> map) {
    return new SomeEntity(value, map.get("anotherKey"));
  }

}

Main.class

public void main(String[] args) {
  ReflectiveDotenv.addAdapter(new SomeEntityAdapter(), SomeEntity.class);
}

You could also simplify this into one line, for example:

public void main(String[] args) {
  ReflectiveDotenv.addAdapter((value, map) -> new SomeEntity(value, map.get("anotherKey")), SomeEntity.class);
}

After which, ReflectiveDotenv should be able to parse the SomeEntity class from hereon as the adapters are added statically (which means it is universal for all instances of ReflectiveDotenv), now let us try to parse this .env into the Configuration class:

.env

key=ARandomKey
anotherKey=ARandomValue

Configuration.class

class Configuration {

  @EnvironmentItem(key = "key")
  public static String someKey;
  public static SomeEntity someEntity;

}

Main.class

public void main(String[] args) {
  ReflectiveDotenv.addAdapter((value, map) -> new SomeEntity(value, map.get("anotherKey")), SomeEntity.class);
  Dotenv.asReflective().reflectTo(Configuration.class);
  System.out.println(Configuration.someKey);
  System.out.println(Configuration.someEntity.response);
}

The expected output of this should be:

ARandomKey
ARandomValue ARandomKey

Now, you might have noticed the annotation EnvironmentItem which is a special annotation used by this library to parse or generate environment variables. For parsing, the only value supported on the annotation is key but you can also set the comment and value values of the annotation to specify what comment should be generated on generation of a new .env file when you call ReflectiveDotenv#create(...), please read below for more information.

🔥 Generating an .env format

You can easily generate a new .env with the help of this library using reflection, similar to the deserialization. For example, we have a Configuration class like:

class Configuration {

  @EnvironmentItem(key = "key", value = "noValue", comment = "This is just some key")
  public static String someKey;
  @EnvironmentItem(value = "0", comment = "This is just some integer")
  public static int someInt;

}

You can easily convert this into a .env through:

reflectiveDotEnv.create(Configuration.class);

And it should output the following:

# This is just some key
key=noValue
# This is just some integer
someInt=0