Environment and Configuration
Accessing environment variables
Java provides access to environment variables via the System.getenv
method. This method retrieves the value of an environment variable at runtime.
final String name = "EXAMPLE_ENVIRONMENT_VARIABLE";
String value = System.getenv(name);
if (value == null || value.isEmpty()) {
System.out.println("Environment variable '" + name + "' not set.");
} else {
System.out.println("Environment variable '" + name + "' set to '" + value + "'.");
}
Rust provides the same functionality of accessing an environment variable at
runtime via the var
and var_os
functions from the std::env
module.
var
function returns a Result<String, VarError>
, either returning the
variable if set or returning an error if the variable is not set or it is not
valid Unicode.
var_os
has a different signature giving back an Option<OsString>
, either
returning some value if the variable is set, or returning None if the variable
is not set. An OsString
is not required to be valid Unicode.
use std::env;
fn main() {
let key = "ExampleEnvironmentVariable";
match env::var(key) {
Ok(val) => println!("{key}: {val:?}"),
Err(e) => println!("couldn't interpret {key}: {e}"),
}
}
use std::env;
fn main() {
let key = "ExampleEnvironmentVariable";
match env::var_os(key) {
Some(val) => println!("{key}: {val:?}"),
None => println!("{key} not defined in the enviroment"),
}
}
Rust also provides the functionality for accessing an environment variable at
compile time. The env!
macro from std::env
expands the value of the variable
at compile time, returning a &'static str
. If the variable is not set, an
error is emitted.
use std::env;
fn main() {
let example_env_variable = env!("ExampleEnvironmentVariable");
println!("{example_env_variable}");
}
In Java, compile time access to environment variables can be achieved, but in a less straightforward way, using Reflection API. Generally this is not recommended in modern Java.
Configuration
Java does not have built-in support for configuration management. In order to work with configuration, we need to use third-party libraries, such as the Apache Commons Configuration library.
Here's the Maven dependency for the Apache Commons Configuration library that we can add to our pom.xml
file:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-configuration2</artifactId>
<version>2.11.0</version>
</dependency>
And here's how we can make use of the library:
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.builder.fluent.Configurations;
import org.apache.commons.configuration2.ex.ConfigurationException;
public class ExampleClass {
public static void main(String[] args) {
Configurations configs = new Configurations();
try {
// Load environment variables
Configuration configuration = configs.systemEnvironment();
// Retrieve the value of the environment variable "ExampleEnvVariable"
String exampleEnvVariable = configuration.getString("ExampleEnvVariable");
System.out.println(exampleEnvVariable);
} catch (ConfigurationException e) {
e.printStackTrace();
}
}
}
A similar configuration experience in Rust is available via use of third-party crates such as figment or config.
See the following example making use of the config crate:
use config::{Config, Environment};
fn main() {
let builder = Config::builder().add_source(Environment::default());
match builder.build() {
Ok(config) => {
match config.get_string("example_env_variable") {
Ok(v) => println!("{v}"),
Err(e) => println!("{e}")
}
},
Err(_) => {
// something went wrong
}
}
}