-
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
Null must be injectable #365
Comments
Do you mean you defined in config source, you will get empty string instead of null. Do you want to get null instead? If not, can you elaborate your use case? |
I'm not sure about myConfig=[nothing] case but more than myConfig doesn't exists and cdi bean uses the snippet I put in the first message, by default I expect it to be null instead of fail (required by tck today). I don't want (also can't in several cases) inject Optional cause it is not serializable and Provider is slow compared to have null. Something like @ConfigProperty(name="...", nullAllowed=true) would be nice. |
or |
sounds weird with Optional class no: "optional=true will set null and you can inject Optional which will not be null" :s? But agree a better phrasing can be found. |
-1 on optional=true, as it contradicts with the contract of "the presence of defaultValue" means optional. How about to add a new constant on ConfigProperty?
Usage:
|
I had that in mind as well so +1 |
Signed-off-by: Emily Jiang <[email protected]>
Signed-off-by: Emily Jiang <[email protected]>
Signed-off-by: Emily Jiang <[email protected]>
Signed-off-by: Emily Jiang <[email protected]>
Signed-off-by: Emily Jiang <[email protected]>
Signed-off-by: Emily Jiang <[email protected]>
The currently proposed solution does not seem correct. One alternative discussed in #512 was to add a separate |
+1 |
Hmm, why isnt it correct? Having a flag or a flag is the same. One is likely more elegant than the other but both are strictly equivalent. |
They are not strictly equivalent. How would you then specify the default value for a nullable property? If default values are implemented using a low priority configuration source (as we do in Quarkus), how do you represent this special behavior? Bear in mind that we already have a recommended approach for optional values, and that is
That is a bit of a stretch, I'd say. Anyway I believe I already proposed in #476 that primitive types should already implicitly default to their Java default values, which I think is probably a cleaner approach. It doesn't make these properties optional, but it does remove boilerplate.
I'm not sure what you mean by this. |
This is the whole point, you can't be both at the same time. If you have a default then you are not nullable so at the end it is just about requesting to accept null as a default. The NULL_VALUE (mp-config 1.4) is exactly there for this case.
As explained before it goes partially against CDI and fully against java recommendation so it can't last IMHO. The last part which was likely unclear is that the coercing of defaults for primitive is not needed in the spec, there is no way to inject a primitive with CDI so no need to spec how to do it. The only existing case it is useful is the case the impl supports configuration proxies (see an example here https://github.com/apache/geronimo-config/blob/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProxyTest.java#L104) but it is out of the spec for now. |
This is factually incorrect. Users can have a property which is optional/emptiable but also has a default value. If they want to explicitly clear the property, they may do so. At least, this works fine on SmallRye/Quarkus.
This should be tackled in a separate issue, since
OK. |
No, the meaning of defaultValue is "use that if not set". There is no way to set null anywhere in the configuration (getValue in a ConfigSource does not return an optional so no way to know it is null or not set at all). What you are speaking about is another topic: how to specify null when there is a default value. In other words it is how to set explicitly null in/from the config source.
Not sure I followed this one. Factually Optional fields do not work in passivable CDI beans so it prevents to use the spec and it is where this issue is coming from. |
This issue has been raised separately and needs to be resolved, IMHO. Personally, I would like to see the empty string
Primitives types are valid beans and injectable per CDI. CDI also specifies that |
The debate about how to indicate nullability in the annotation is largely driving by limitations in the expressiveness of annotation structures. I think the guiding principle here is that we need to avoid further complicating the interpretation of value strings by overloading the use of the It can certainly be argued that this is ambiguous at a glance: @ConfigProperty(name = "foo", nullable = true, defaultValue = "bar")
String foo; But so is this: @ConfigProperty(name = "foo", defaultValue = "bar")
Optional<String> foo; It is easy enough to specify that |
Maybe the real issue here is the <T> T getValue(String propertyName, String defaultValue, Class<T> propertyType); So why should we provide such convenience during injection? As recommended in the javadocs, a developer is almost certainly better off simple bundling the default values in |
+1 here
We support this case. Having a default is not the same as making a property be required (if you assume the reverse, all kinds of ambiguous situations appear, as previously discussed).
This has been proposed. But using a config source is more future-proof (calling back to the property expansion discussion). |
In case this is helpful, it would seem to me that CDI-validation-time of configuration injection points is effectively impossible, since it is (apparently?) deliberately (currently) unspecified whether |
Hmm, i think it is specified by the api: configsources are constant for a config instance - we still dont have a way to add/remove it even if a custom source can facade others. However it is also specified that their properties can change and that config is dynamically recalling sources when needed - no cache. Combined with cdi which can recreate bean instances - including appscope ones - it means all is dynamic so validation only makes sense if the app creates a "business" instance at startup without reload. |
I think exploring integration with bean validation would be a good idea for 2.0. |
Bean Validation is something that should be explored overall in MP, not only with Config, but with other specs, for instances OpenAPI / Bean Validation. I see no reason why we need to duplicate BVal annotations and OpenAPI annotations to declare validations in our openapi document. |
Side note: bena validation being already cdi integrated it already works ;) |
…le#365 Signed-off-by: Emily Jiang <[email protected]>
+1 for potentially adopting bean validation as the mechanism, but we still have to decide if injecting to a non-optional type implies I'm still a little unclear on whether the motivation of raising this issue was to avoid validation or to actually support I think if Per @dmlloyd 's notes above, we don't want to start an My personal opinion is that low-level APIs like Config should match the lowest common denominator of the platform. Like it or not, Java has |
The original issue was just to enable an unconfigured value to end up as null in the injection point. This is why NULL_VALUE was doing the job. |
+1, this is clearly the stance of the API.
Changing a method that previously never returned |
BTW my personal opinion is to stick with "team |
@dmlloyd as a side note, please note this is NOT a breaking change because before the deployment was invalid so the configs are there for all working apps, it will just enable new configs to be null. |
It is breaking in cases where failing deployment validation is the desired behavior (this would be the definition of "required configuration": such configuration is required and the application should not start up if it is missing). Today any configuration that is not |
Hmm, not sure I see your point about:
Means it is breaking broken cases? Sounds quite acceptable to me. That said it brings another argument to remove any validation from the spec: the moment it is validated is more complex than just the startup or instantiation, a whole bunch of code is validated lazily or just not validated in applications due to the libraries layers and condition it encounters. I just met it about a HTTP client, JDBC pool and LDap client configurations. |
I can see the argument of a breaking change. I've seen teams that use this to validate that deployments have everything set in their containers, to force DevOps or admins to set the correct values (you may agree or not with the use case). We need to weight things like these before making the decision. |
You seem to be directly saying that you think that requiring a configuration property is broken behavior. Is that correct?
Given the config may in some cases be external to the application, I believe this is a real possibility, and starting up the application without a required configuration property (leading to possibly undefined behavior) is demonstrably worse than failing the deployment.
OK but surely you must agree that removing all validation from the specification is clearly a bigger discussion? Essentially you're positing use cases which are substantially different from those which have been posited before. Those use cases may be valid and even important but we can't derail every discussion for incremental improvement because of them, otherwise the spec is essentially dead. |
No, that today it is indeed correctly configured so that it will not introduce a breaking change to relax this. The feature by itself makes sense and can already be covered by any validation interceptor. About if the discussion is bigger or not, I'm not sure but it sounds like a good exit door for all this thread to me. No issue on my side if it requests more discussion, PoC or tests on your side. I'm just trying to make MP matching real life use cases without having to use workarounds. |
I think we need to collect these use cases, for 2.0 if possible, so I expect this will resurface again soon. |
If the ability to inject Otherwise, I think the non-breaking way forward is a new config method to retrieve potentially null values: String foo = getNullableValue("foo", String.class); and an equivalent injection mechanism: @Inject
@Nullable
@ConfigProperty(name="foo")
String foo; In contrast to adding a property to the existing annotation, introducing a new annotation makes it clear that nullability applies only to the injection site, instead of potentially confusing the issue of whether or not to apply a default value when retrieving the config value. |
Hmm, and then we will need default value handling (to use converter chain) in Config so we'll add getValueWithConverters and getNullableValueWithConverters etc? This is why i proposed a getValue(ValueRequest) method. I don't know if |
This discussion seems to have run out of steam, and there are so many comments and directions of the discussion that it is no longer useful for the issue to remain open. If we want to introduce any ideas from this issue, please either open a new issue labeled |
It must be allowed to inject that and get null, a workaround is to use an optional but it is not recommanded (even the opposite) to use optionals as fields so this is not a solution. Injecting null is fine from all point of views and compatible with mainstream config solution so it should probably make its path in mp-config asap.
The text was updated successfully, but these errors were encountered: