-
Notifications
You must be signed in to change notification settings - Fork 116
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
CDI @ConfigProperty default value consistency should be enforced #475
Comments
An alternative is to explicitly specify that default values given in |
One challenge here is that the only way that equivalence can be enforced would be to cause the container to fail to deploy the application. But we don't really have any way to test that this happens in the TCK. Should we go ahead with the spec change, with wording like "The container may cause the application to fail" or something like that? |
I don't think we should do this, primarily because I don't think that an annotation on one injection point should affect a value injected at another injection point. @Inject @ConfigProperty(value="foo", defaultValue="bar")
private String baz; should be seen as the CDI equivalent of String baz = Config.getConfig().getOptionalValue("foo", String.class).orElse("bar"); If you need to set the default for a config value across your application, this can be done in the |
Yes, that works and aligns with the proposal of default values being scoped to the injection point, but then these should be excluded from property expansion. Consider: @Inject
@ConfigProperty(value="foo", defaultValue="bar")
private String bar
@Inject
@ConfigProperty(value="foo", defaultValue="baz")
private String baz
expand=${foo}
Config.getConfig().getOptionalValue("expand", String.class); Which one gets expanded into |
Assuming "foo" is not defined, neither. Edit: So yes, would also say that the default value in |
If you want to assign a default value to @Inject
@ConfigProperty(value="foo")
private String bar
@Inject
@ConfigProperty(value="foo")
private String baz
foo=bar
expand=${foo}
Config.getConfig().getOptionalValue("expand", String.class); |
Alternatively, you could define an expansion syntax which allows for a default value to be provided, but I'm not sure this provides much of an advantage over just defining the default in a config source with a low ordinal. E.g. With this syntax, we'd not be defining a global default, we'd just be setting the value to use in this location if no value exists for the given property. |
Correct. Yes, all of your suggestions are possible and we should probably document them / add them, but we cannot prevent the user for making the described mistake, so the spec needs to specify what should happen in that case. The easiest is to just say that default values cannot be used for expansion. |
@Azquelt I originally had the same opinion, however IIRC Quarkus users almost immediately complained about it - the expectation was really that a default value gets expanded when a property expression references the corresponding property. So I've since revised my view. I think it is logically an error to define the same property at two points with different default values, and I've come to think of the default value as applying to the configuration as a whole; I think this world view is a lot more practical for most users. Also it is my opinion that single value injection in CDI was a design error, which is something we're exploring in SmallRye right now (smallrye/smallrye-config#279 to see that discussion). I'm feeling more and more that:
We'll be exploring these ideas in SmallRye and we will report back our findings as we have them. |
If that's actually the case, then possibly we should consider removing the My expectation would be that it's tied directly to the specific injection point and I'd be very surprised if it caused a change in behaviour anywhere else.
How would this be different from saying that default values should be stored in |
My opinion on that is only that (as I said earlier) I feel that the CDI mechanism was mis-designed from the start. If we have a "higher" notion of a configuration object that aggregates the various configuration properties for an application, then suddenly we're referencing configuration rather than a configuration property, and the configuration object itself now logically better aligns with the notion of declaring what properties are expected to be present (and what are optional), along with their default values. But failing that, at least making default values be uniform moves the needle in the right direction (as far as I can see it).
This depends on what you're configuring and how. MP Config is open-ended: configuration sources may be higher or lower than the JAR's So I don't think that |
By the way, the design of defaultValue on the injection is only scope to that injection point. I argue what the attemption to use it for variable expansion is not a good design. The variable expansion should ignore the defaultValue. There is no problem as yet. We can clearly spell out when we add variable replacement. The variable replacement should only work on config source defined properties. If the property does not exist, no expansion should happen.
If you want to set some default with multiple jars potentially using the same config, it is best to put that config outside the jar, e.g. system properties, environment variables. This is design principles though. |
Stumbled upon this when preparing a bit for yesterdays weekly meeting and just want to share a thought.
Doesn't this also imply that values would not be allowed to change? |
No, because even if a value for a property changes, there's still only one single value. Not that I'm in favor of config source mutability (I'm not) but it's essentially a reality today. But I'd say that default values should not be allowed to change, just for the sake of the user's sanity. |
I'm still unravelling the statement and its consequences in my head. The way I understand it is that if there would be multiple defaults you would not know which one to pick when resolving the substitution. While I can follow this thought I don't see how it applies as defaults are passed by callers, so if a caller resolves a property which then causes a substitution with a value which itself is a property that property would be resolved with no default (as you can't even pass one as caller) so it would not matter if there are call sides for this property which do provide different defaults. |
I don't think defaults should be allowed to be passed by callers because it confuses the situation immensely. Also I think users will be very confused about when to pass a default vs when to use |
After discussing this in yesterdays weekly meeting I first grasped the entirety of this proposal. I try to summarised it again in my own words so that it might help others in getting an understanding. The issue: The same property can be injected multiple times using The proposal is this: On deployment CDI
The goal is to make defaults apply consistently independent of where and how the lookup was made. |
Additionally, we can consider to add an API to provide the default values and deprecate |
@jbee and @Emily-Jiang discussed this a bit more now. @jbee suggested to create an inmemory config source with a lowest config_ordinal, which is used when the config properties are not specified in other config sources. In this way, it can force the value consistence. If the same config property has multiple different values, which one wins depends on which injection point is scanned first. This suggests the defaultValue is global as the value will be used by other injection even though defaultValue is not specified as well as config.getValue() look up. Thoughts? |
Does that mean: @Inject
@ConfigProperty(value="foo", defaultValue="foo")
private String bar
@Inject
@ConfigProperty(value="foo")
private String baz That:
|
yes |
Ok, I'm fine with this. In SmallRye, we added a specific API at the Builder level to contribute default values. |
If the same configuration property is given more than once via the
@ConfigProperty
annotation, they should be enforced to have the same default value string, or else an error should result.This is a necessary prerequisite to #405; if multiple default values are allowed for a given property, then it becomes impossible to define which value would be returned for an expression string which references that property.
The specification text for
@ConfigProperty
should be updated to this effect.The text was updated successfully, but these errors were encountered: