Dynamic keys

38 views
Skip to first unread message

Justin Ashworth

unread,
Oct 1, 2014, 4:12:48 PM10/1/14
to owne...@googlegroups.com
Hi all,

I am evaluating configuration frameworks and have a need that I'm not sure Owner can support. I'd just like to confirm my understanding and possibly suggest a solution before ruling out Owner as an option.

I see the variable expansion in keys, which is great. However, it's based on the value of another key rather than a runtime parameter. In my case I'd like to define keys such as this:

Country.Preference.1=UNITED STATES
Country.Preference.2=GERMANY
Country.Preference=CANADA # Default - this does need to be in config so can't be in a defaultvalue annotation.

And I'd like to pass the value for "1" or "2" as a parameter at runtime when I request the property value. I cannot define these values as an array because the keys will not always be sequential.

Would it be possible to have the values returned as a Map? I see in the documentation that the Map interface and sub-interfaces are not supported. But suppose I defined a getter like so:

ConfigMap<String, String> countryPreference();

Then usage like this:

cfg.countryPreference().get("1")   => Result in "UNITED STATES"
cfg.countryPreference().get("2")   => Results in "GERMANY"
cfg.countryPreference().get("ANYTHING ELSE")   => Results in "CANADA"

The ConfigMap class would just subclass HashMap and override get() to handle the default case.

Thanks,

Justin

Luigi R. Viggiano

unread,
Oct 2, 2014, 6:18:56 AM10/2/14
to owne...@googlegroups.com



Hi Justin.

 
I see the variable expansion in keys, which is great. However, it's based on the value of another key rather than a runtime parameter.

OWNER variables expansion can work also with system properties a on runtime parameters and eventually system properties or other Maps.

In the same link you posted there is also this example:

@Test
public void testKeyExpansionFromAnotherKeyWithImportOverriding() {
    ExpandsFromAnotherKey cfg = ConfigFactory.create(ExpandsFromAnotherKey.class, map("env", "uat"));

    assertEquals("UAT", cfg.name());
    assertEquals("uathost", cfg.hostname());
    assertEquals(new Integer(60020), cfg.port());
    assertEquals("myuser2", cfg.user());
    assertNull("mypass2", cfg.password()); // expansion is disabled on method level
}


As parameter to the create() method, you see I am specifying a map("env", "uat"), which you can specify at runtime. Those values are "copied" so if you change the map later, it will not be reflected; so this won't work:

Map replacements = new HashMap() {{ put("env", "uat"); }}
Config cfg = Config.create(WhatEverConfig.class, replacements);
replacements.put("env", "prod"); // this will not be reflected in cfg! 

Does this cover your use case?
 


 
In my case I'd like to define keys such as this:

Country.Preference.1=UNITED STATES
Country.Preference.2=GERMANY
Country.Preference=CANADA # Default - this does need to be in config so can't be in a defaultvalue annotation.

And I'd like to pass the value for "1" or "2" as a parameter at runtime when I request the property value. I cannot define these values as an array because the keys will not always be sequential.

Would it be possible to have the values returned as a Map? I see in the documentation that the Map interface and sub-interfaces are not supported. But suppose I defined a getter like so:

ConfigMap<String, String> countryPreference();

Then usage like this:

cfg.countryPreference().get("1")   => Result in "UNITED STATES"
cfg.countryPreference().get("2")   => Results in "GERMANY"
cfg.countryPreference().get("ANYTHING ELSE")   => Results in "CANADA"

The ConfigMap class would just subclass HashMap and override get() to handle the default case.

This is not supported.

Still I think that if you need to access some properties as a Map<String, String> probably you can use a plain Properties.getProperty("key", defaultValue) approach for the specific case, which is not precluded by OWNER: 


Your Config object class needs to implement Accessible in order to have the getProperty() method exposed.


I got a pull request some time ago which was introducing some Map support. But I didn't like the implementation. Also a full Map support should also allow conversion so it should be restricted to Map<String, String> but be open to all java types and objects.
This feature should be deeply analysed before being implemented, and still I can't find a fully convincing behaviour for this. 


Hope this helps.

Luigi.

Reply all
Reply to author
Forward
0 new messages