owner
owner copied to clipboard
Nested configuration interfaces
Hi, I've just came across your project and I really like it. I'd like to use it in our project and I have one question. Is it possible to create a configuration interface with additional nested interfaces.
An example of the idea:
public interface AppConfig {
DatabaseConfig db();
}
public interface DatabaseConfig {
String url();
String user();
String password();
}
And the corresponding properties configuration:
db.url=localhost
db.user=admin
db.password=pass
I would expect to pass the AppConfig to the ConfigFactory.create() and get the whole structure populated, including the nested interface. In the current version (1.0.8) this does not seem to work. Am I doing something wrong or is this not supported? Do you think it makes sense to implement this in a future version?
Why would you need nested configuration for this case? For your configuration you can have one interface and three keys/methods like this:
@Key("db.url")
String url();
Perhaps, you have some more difficult use case in mind? Anyway.. you could achieve the desired effect by doing something like this:
@Sources({"file:db.properties"})
interface AppConfig extends Config {
@DefaultValue("db")
@ConverterClass(DatabaseConfigConverter.class)
DatabaseConfig db();
}
@Sources({"file:db.properties"})
public interface DatabaseConfig extends Config {
@Key("${db}.url")
String url();
@Key("${db}.user")
String user();
@Key("${db}.password")
String password();
}
public class DatabaseConfigConverter implements Converter<DatabaseConfig> {
@Override
public DatabaseConfig convert(Method method, String input) {
Map<String, String> imports = new HashMap<String, String>();
imports.put("db", input);
DatabaseConfig dbConfig = ConfigFactory.create(DatabaseConfig.class, imports);
return dbConfig;
}
}
public class Main {
public static void main(String... args) {
AppConfig appConfig = ConfigFactory.create(AppConfig.class);
DatabaseConfig dbConfig = appConfig.db();
System.out.println("url: " + dbConfig.url());
System.out.println("user: " + dbConfig.user());
System.out.println("password: " + dbConfig.password());
}
}
Indeed, I had a more complex case in mind. When you have larger configuration with many section, it's actually better to split into multiple interfaces and not having tens or hundreds of methods in one interface. My example was shortened just to explain what I want to achieve.
Thanks a lot for your suggestion, I believe this principle can be successfully used to achieve the desired behavior with just a small overhead code. From my point of view, it still would be nice if this is the default behavior without the need to add a custom Converter, but I am happy to have a solution with the current version.
The proposed solution is good when you don't know the name of some property (section). But if all properties' names are known beforehand and you just want to make a logical split into multiple interfaces, then you could use following approach:
@Sources({"file:app.properties"})
interface MyDbConfig extends Config {
@Key("db.url")
String url();
@Key("db.user")
String user();
@Key("db.password")
String password();
}
@Sources({"file:app.properties"})
interface MyFileConfig extends Config {
@Key("file.path")
String file();
@Key("file.extension")
String extension();
}
@Sources({"file:app.properties"})
interface MyAppConfig extends MyDbConfig, MyFileConfig {
}
public class Main {
public static void main(String... args) {
MyAppConfig appConfig = ConfigFactory.create(MyAppConfig.class);
System.out.println("url: " + appConfig.url());
System.out.println("user: " + appConfig.user());
System.out.println("password: " + appConfig.password());
System.out.println("file: " + appConfig.file());
System.out.println("extension: " + appConfig.extension());
}
}
Getting rid of multiple @Sources's was already proposed in some other thread.
I'm sorry for going a bit off topic here, but I could not find any thread explaining how to get rid of multiple @Sources
. Any hints?
There is no thread which explains how to actually get rid of multiple @Sources. There is just a thread where this issue was brought up and considered to be doable: https://github.com/lviggiano/owner/issues/128
I'm sorry for going a bit off topic here, but I could not find any thread explaining how to get rid of multiple @Sources. Any hints?
Have you seen #145 - would you like giving some feedback there?