Building Configuration Hierarchy and Overriding

In this lesson, we will learn to build levels of configuration hierarchy.

Configuration hierarchy overview #

  • The framework should bundle the default value for all the configurable parameters in a configuration file.
  • These default values should be overridable from a project-specific configuration file.
  • These project-specific configuration parameters should be overridable by passing as a JVM argument (i.e., -Dkey=value).

Designing the configuration manager #

  • The reading of configuration files needs to happen only once. This can be achieved by using the Singleton Pattern for the creation of the file object.

  • The configuration file can be any of these formats: .properties, .ini, .xml, .json, .yaml, .toml.

  • We can use an appropriate library for reading the configuration files for fetching the configuration parameters.

Configuration overriding #

First, the configuration will be looked up in the JVM arguments, so it can be passed from the command line as shown below:

-Ddatabase.enabled=true

If the configuration is not passed through the command line, it will be looked up in the project-specific configuration file.

project-specific-config.properties

database.enabled = true

If the configuration parameter is not passed through the command line or a project-specific file, then it will fallback to the default configuration file.

default-config.properties

database.enabled = false

The below ConfigurationManager class is a sample implementation demonstrating configuration hierarchy overriding. For demonstration, we have used .properties file format.

import java.io.IOException;
import java.util.Properties;

public class ConfigurationManager {

	private ConfigurationManager() throws IOException {
		PROPERTIES.load(ConfigurationManager.class.getResourceAsStream("default-config.properties"));
		PROPERTIES.load(ConfigurationManager.class.getResourceAsStream("project-specific-config.properties"));
	}

	private static ConfigurationManager manager;

	private static final Properties PROPERTIES = new Properties();

	public static ConfigurationManager getInstance() {

		if (manager == null) {
			synchronized (ConfigurationManager.class) {
				if (manager == null) {
					try {
						manager = new ConfigurationManager();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
		return manager;
	}

	public String getProperty(String name) {
		return System.getProperty(name, PROPERTIES.getProperty(name));
	}
}

The code below reads the configuration parameter’s value, and the overriding happens in the ConfigurationManager class while fetching the value.

boolean isDatabaseEnabled = "true".equalsIgnoreCase(ConfigurationManager.getInstance().getProperty("database.enabled"));

Get hands-on with 1000+ tech skills courses.