How to switch from a hardcoded static config file to a .properties file?
java, refactoring
Solution
Here is a piece of a code I have used in the past - that can be adapted to your example:
public enum Configuration {
PROPERTY1("property1.name", "default_value_1"),
PROPERTY2("property2.name", "default_value_2");
private final String key;
private String defaultValue;
Configuration(String key) {
this(key, NA);
}
Configuration(String key, String defaultValue) {
this.key = key;
this.defaultValue = defaultValue;
}
private final static Logger logger = LoggerFactory.getLogger(Configuration.class);
private final static String NA = "n.a.";
private final static String CONFIG_FILE = "properties/config.properties";
private final static String NOT_A_VALID_KEY = "Not a valid property key";
private final static Map<Configuration, String> configuration = new EnumMap<>(Configuration.class);
static {
readConfigurationFrom(CONFIG_FILE);
}
private static void readConfigurationFrom(String fileName) {
logger.info("Reading resource: {}", fileName);
try (InputStream resource = Configuration.class.getClassLoader().getResourceAsStream(fileName);) {
Properties properties = new Properties();
properties.load(resource); //throws a NPE if resource not founds
for (String key : properties.stringPropertyNames()) {
configuration.put(getConfigurationKey(key), properties.getProperty(key));
}
} catch (IllegalArgumentException | IOException | NullPointerException e) {
logger.error("Error while reading the properties file {}", fileName, e);
populateDefaultValues();
}
}
private static Configuration getConfigurationKey(String key) {
for (Configuration c : values()) {
if (c.key.equals(key)) {
return c;
}
}
throw new IllegalArgumentException(NOT_A_VALID_KEY + ": " + key);
}
private static void populateDefaultValues() {
for (Configuration c : values()) {
configuration.put(c, c.defaultValue);
}
}
/**
* @return the property corresponding to the key or null if not found
*/
public String get() {
return configuration.get(this);
}
}
Problem
I have some code that uses a class holding a huge lot of hardcoded constans. This is what it looks like: ``` class Constants{ public static final String name1 = "value1"; public static final String name2 = "value2"; public static final Integer value3 = 3; ... and so on } ``` These constants are used everywhere in the code like `Constants.name1`. What I need to do now is to make it possible to specify values for these constants in a configuration file, probably a `*.properties` file. My question is: what is the best way to do it, having to rewrite as little code as possible? I thought of using a single configuration class which reads properties from file when instantiated, but then I'll have to replace all the static calls of values to calls to an instance of that class and I'll have to alter existing methods to pass this config instance into them. Is there a better way?