Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access to config value metadata using a ConfigValue wrapper #43

Closed
starksm64 opened this issue Feb 2, 2017 · 21 comments
Closed

Access to config value metadata using a ConfigValue wrapper #43

starksm64 opened this issue Feb 2, 2017 · 21 comments
Labels
use case 💡 An issue which illustrates a desired use case for the specification
Milestone

Comments

@starksm64
Copy link
Contributor

As far as I can see from all of the current proposals, the Config.get(...) is returning a resolved value that has thrown away any notion of the source and conversion information. Wouldn't it be better for the base return value from Config.get(...) to be a ConfigValue that maintains the information along the lines of:

public interface ConfigValue {

/**
 * Return the resolved property value with the specified type for the
 * specified property name
 * 
 * @param <T>
 *             the property type
 * @param propertyType
 *             The type into which the resolve property value should get converted
 * @return the resolved property value as an Optional of the requested type.
 */
<T> Optional<T> getValue(Class<T> propertyType);

/**
 * Get configuration value propertyName.
 *
 *             
 * @return The configuration propertyName.
 *
 */
String getName();

/**
 * @return all currently registered {@link ConfigSource}s for this value
 */
Iterable<ConfigSource> getConfigSources();

...

@Emily-Jiang
Copy link
Member

Can you describe your user case? You can obtain a list of config sources from config in an ordered fashion. If you want to find out the serving config source for a particular config, if you search search the config source and the first config source found will be the config owner. I don't see how frequent you need to retrieve its source. Therefore, I don't think it is necessary to return a wrapper again.

@starksm64
Copy link
Contributor Author

The use case is that in a management interface that is allowing runtime editing/viewing of the existing configuration, one can see an annotation for the source of the current value. Although this does not have to happen from the value level itself, it is simpler, and it lends itself as the point for extensions we have discussed down the road such as change listeners, etc.

@struberg
Copy link
Contributor

struberg commented Feb 3, 2017

Hi Scott!
ConfigSources are not intended to be modified by a user. Each ConfigSource can of course provide it's very own way to change configured values.
And for just looking up which ConfigSource contains a value you can also easily iterate over the ConfigSources and ask each of them on it's own.
Any change-listener approach would need a much deeper integrated functionality imo.

The reason for the ConfigValue is to allow functionality which needs to keep some state. E.g. the last load time, previously loaded values, etc.

There are 4 features I like to get covered in our Config system. We do not need to implement all of them now, but they are all useful:

  • variable replacement, e.g. myprj.url=http://${myprj.archive.server}/docs
  • dynamic reloading / caching: val.cacheFor(5, TimeUnit.MINUTES);
  • postfix based lookupchains: e.g. myprj.url.production vs myprj.url.development vs myprj.url (default value). 2 ways needed: a.) lookup based on string postfix, b.) based on another config entry.
  • List handling: comma separated values might get picked up as List

Happy to discuss those in our next hangout.

@keilw
Copy link
Contributor

keilw commented Feb 3, 2017

I don't think Scott was talking about a ConfigSource but more values in a Config element.
Even a bit more specialized than MP Config, but many (especially @starksm64 ) will know JSR 107 and e.g. the https://github.com/jsr107/jsr107spec/blob/master/src/main/java/javax/cache/configuration/MutableConfiguration.java. It allows to modify configuration elements. Whether you do it that way or via a complete "clone" for editing the configuration, there may be multiple ways (each has benefits and penalties, e.g. memory etc.) but in a dynamic "Cloud" or Microservice environment you don't just have the good old static files you once write and then never touch after starting your service. Therefore some users maybe with a certain role (that's where security and identiy efforts come into play) must be allowed to change config on particular nodes or services. Others may only consume the read only config.

@starksm64
Copy link
Contributor Author

Right, I'm talking about a ConfigValue as returned from a Config. A default method on Config could provide the source for a given property, but it just seems like there are a number of uses for having a value wrapper to build features on. I have asked Heiko to comment on this as well as he is much deeper into our config and management requirements.

@heiko-braun
Copy link

heiko-braun commented Feb 6, 2017

I think we shouldn't get caught up on the mutation of config values, which I think isn't @starksm64 primary use case. What he seems to be proposing instead is an intermediary to connect to related use cases to the layer of config sources and values.

One of these related cases may be to access to pure meta data (origin of a config value) or listening for change events amongst other things.

Personally I think there is a lot of value for such an intermediary being a first class citizen. In particular when thinking about cases that we don't cover in the first iteration, but that might become relevant in the future.

As an alternative to Scott's proposal I can think of an a separate API to get hold of these intermediaries, rather then attaching it to the config value directly. This would keep access to configuration values like in the current proposal, but also support future use cases leveraging the intermediary objects.

@keilw
Copy link
Contributor

keilw commented Feb 6, 2017

Some sort of DTO maybe, at least that's what the types of services here in current banking gig use (increasingly based on either Microservice or SCS pattern)

@OndroMih
Copy link
Contributor

OndroMih commented Feb 7, 2017

First I wanted to oppose this suggestion, but I realized that the getValue method already returns Optional, which already adds a layer of indirection. A problem with optional is that is a final class, and therefore it cannot be enhanced in the future. If you return ConfigValue and copy over all methods from Optional instead, we can easily add new methods later without breaking changes. And no additional layer of redirection is added on top of the current proposal.

And with further additions, I'm not speaking only about metadata, but also about possibility to add better support for programming constructs or copy the methods planned for Java 9 and have it already with Java 8.
ConfigValue can later easily extend from a common custom Optional class/interface, which is not possible with Java SE Optional (which is a final class)

@struberg
Copy link
Contributor

@starksm64 Emily and I are currently walking through the open issues. Are you happy with the current ability to implement your use case or do you have additional needs?

txs and LieGrue,
Emily and strub

@starksm64
Copy link
Contributor Author

It seems like a few people are interested in an ability to obtain a single DTO representation of the composed value of a property from a Config. If it is not the actual return value, is there an api to access such a value?

@struberg
Copy link
Contributor

struberg commented Mar 10, 2017

@starksm64 you mean something like

Map<String, String> Config.filter("org.mycomp.somepkg") 

?

If not, can you share a code sample of how you envision it to work? /cc @heiko-braun

@starksm64
Copy link
Contributor Author

I was thinking something like this, which the sourceValues ordered by priority from highest to lowest:

List sourceValues = Config.filter("org.mycomp.somepkg")
class ConfigValue {
Optional<?> getValue();
ConfigSource getSource();
}

@Emily-Jiang
Copy link
Member

@starksm64 Can you attend the hangout on 27th April to discuss this further?

@starksm64
Copy link
Contributor Author

Yes.

@Emily-Jiang
Copy link
Member

Thanks @starksm64 ! Talk to you then.

@Emily-Jiang
Copy link
Member

Emily-Jiang commented Apr 27, 2017

@starksm64 and I met on 27th April and discussed this further. This sounds a good feature for config 1.1. e.g. add one more method to config.getWrappedValue(...) to return a wrapped value, which can trace back to the config source that provides the config value.

@OndroMih OndroMih changed the title Keep some notion of the hierarchical nature of a config value Access to config value metadata using a ConfigValue wrapper Apr 16, 2018
@OndroMih
Copy link
Contributor

It seems like this proposal also suggest to have a ConfigValue wrapper, although for a different usecase: #91

@Emily-Jiang Emily-Jiang added this to the MP Config 2.0 milestone Feb 13, 2020
@Emily-Jiang
Copy link
Member

I think it is good idea to introduce ConfigValue as a wrapper to contain a few methods to perform variable replacement, default, which configsource the value comes from etc.

@dmlloyd
Copy link
Contributor

dmlloyd commented Feb 13, 2020

In other words, a config accessor?

Also, does this really merit a whole label? Will we be having labels for every implementation idea now?

@Emily-Jiang
Copy link
Member

Use case:
As a developer, I would like to know where my config value is from.

@Emily-Jiang
Copy link
Member

Close this issue as the PR from @radcortez has been merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
use case 💡 An issue which illustrates a desired use case for the specification
Projects
None yet
Development

No branches or pull requests

7 participants