CNF-01 is a library that provides immutable configuration for Java projects. Immutability is achieved by converting the configuration source into an immutable Map. The resulting configuration Map can’t be altered even with modifying the underlying source.
-
Provides immutable configurations for:
-
configuration files / path properties (
PathConfiguration
) -
System Properties (
PropertiesConfiguration
) -
environment variables (
EnvironmentConfiguration
) -
command line arguments (
ArgsConfiguration
)
-
-
Default configurations in case the provided configurations from a source are not found or are otherwise broken (
DefaultConfiguration
)
All the sources are usable with the same Configuration
-interface. It has a single function:
Map<String, String> asMap() throws ConfigurationException;
In Java, System properties can be utilized with System.setProperty(key, value)
.
System properties can be used as a configuration source in CNF-01 with the PropertiesConfiguration
object. It has two constructors:
public PropertiesConfiguration(); // uses System.getProperties()
public PropertiesConfiguration(Properties properties); // uses any Java Properties given
Most likely the default constructor is what you’ll need, but in some cases the second constructor might become handy.
Here’s an example of using PropertiesConfiguration
:
PropertiesConfiguration config = new PropertiesConfiguration(); // uses System.getProperties()
Map<String, String> result = config.asMap();
One of the supported configuration sources is a File
. These are often marked with a ".properties" file extension but basically any Java’s File
object will do. The properties have to be given in a key=value
format in the File
. For example:
bar=foo
foo=bar
A file can be used as a configuration source with the PathConfiguration
object. It has two constructors:
public PathConfiguration(final String fileName); // Uses the filename
public PathConfiguration(final File file); // Uses Java's File object
Here’s an example of using PathConfiguration
:
Configuration configuration = new PathConfiguration("file/path");
Map<String, String> configMap = new HashMap<>();
try {
configMap = configuration.asMap();
} catch (ConfigurationException e) {
// Handle the exception...
}
PathConfiguration
throws an exception if the File
is not found.
Read Default Configuration section to see how default configurations can be used to avert the need for the try-catch.
Command line arguments (or any String[] args
) can be utilized as a configuration source with the ArgsConfiguration
object.
Here’s an example of using ArgsConfiguration
:
public static void main(String[] args) {
Configuration configuration = new ArgsConfiguration(args);
Map<String, String> configMap = new HashMap<>();
try {
configMap = configuration.asMap();
} catch (ConfigurationException e) {
// Handle the exception...
}
}
ArgsConfiguration
throws an exception if the Strings in the array don’t follow the key=value
format.
Read Default Configuration section to see how default configurations can be used to avert the need for the try-catch.
EnvironmentConfiguration
object supports Java’s System.getenv()
, meaning the system’s environment variables. The constructor takes no arguments.
Here’s an example of using EnvironmentConfiguration
:
Configuration configuration = new EnvironmentConfiguration();
Map<String, String> configMap = configuration.asMap();
Default configurations can be used in case the asMap()
function throws ConfigurationException
. If the function throws an exception, the defaults are used instead. Only PathConfiguration
and ArgsConfiguration
can currently throw an exception.
DefaultConfiguration
follows the pattern of composable decorators introduced in Elegant Objects. Therefore, it takes another Configuration
object as an argument in the constructor. The second argument is an ImmutableMap
which is in the CNF-01 library as well.
Here’s an example of how to use DefaultConfiguration
when paired with PathConfiguration
:
Map<String, String> map = new HashMap<>();
map.put("foo", "bar");
ImmutableMap<String, String> defaults = new ImmutabilitySupportedMap<>(map).toImmutableMap();
DefaultConfiguration defaultConfiguration = new DefaultConfiguration(
new PathConfiguration("invalid.path"), // uses PathConfiguration that will throw an exception
defaults
);
Map<String, String> result = defaultConfiguration.asMap();
The configuration Map from CNF-01 shouldn’t be used directly in regular objects. It should only be passed to objects that are responsible for providing configured versions of other objects, in other words, Factories. The regular objects must not be configurable!
Small example with an Example
object:
ExampleFactory exampleFactory = new ExampleFactory(configurationMap);
Example example = exampleFactory.example();
Here, the logic for instantiating an Example
is in the ExampleFactory
object, which receives the configuration map from CNF-01 as a parameter. This ensures that the main object Example
is as clear as it can be.
You can involve yourself with our project by opening an issue or submitting a pull request.
Contribution requirements:
-
All changes must be accompanied by a new or changed test. If you think testing is not required in your pull request, include a sufficient explanation as why you think so.
-
Security checks must pass
-
Pull requests must align with the principles and values of extreme programming.
-
Pull requests must follow the principles of Object Thinking and Elegant Objects (EO).
Read more in our Contributing Guideline.
Contributors must sign Teragrep Contributor License Agreement before a pull request is accepted to organization’s repositories.
You need to submit the CLA only once. After submitting the CLA you can contribute to all Teragrep’s repositories.