-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Introduce ApplicationConfig #1683
Conversation
builder.withSources( | ||
inJar, | ||
// the ordinal of 240 because it's slightly lower priority then what inJar uses | ||
new PropertiesConfigSource(appStateProperties, "appState", 240)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't the right way to set default values.
The best way to do it is to just use the defaultValue
property on the @ConfigItem
. The second-best way is to just implement whatever default behavior you want when the properties are not present in the config object. The third-best way would be to produce default value build items. Adding a config source doesn't even make the list unfortunately. ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you (or anyone) find yourself modifying the core configuration code or the core mojos or main methods in order to add a configuration switch, then a wrong turn was taken at some point. The configuration and build item infrastructures exist so that we don't have to do these things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really wanted to use defaultValue
, but the problem is that default needs to be dynamic, in the sense that it depends on what is in the build.
My idea was that the "client" processors would just inject the ApplicationConfig
and not have to worry about how to set default values if users don't.
So just to verify, what your proposing is that the processors would inject ApplicationConfig
which would contain whatever the users set and then would also have to inject the default values in some other way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The build step (singular) would accept the config and produce the build item with the actual app name in it. The build step would also calculate the default value for the build item in the event that it was not given in the config. Everything which needs the application name and/or version would consume the build item.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, got it thanks for the explanation!
So I implemented it the other way around. But I still don't understand how I would pull the default values (like the artifactId
for the name) unless I am pushing them in when setting up the Augmentor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The kubernetes extension would definitely need those values as well (by the means of injecting a build item that contains the final values).
I really like the idea of having these values settable in application.properties
, but I think it would require a fair amount of work. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as the Kube extension just consumed that build item, and assuming it was produced as I described above, it should just work with a minimum of effort.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having the extension read the config should be easy once everything is in place. The difficulty I see is having all the config (like wiring classes) driven by application.properties
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see. Well it doesn't make sense to force 100% of everything through properties. It's more like two polar endpoints: at one end, all application-wide config must be driven by application.properties
, and at the other end, any per-class or per-member behavior should be driven by annotations. In between is where we consider factors to determine if it makes sense to make some configuration be driven one way and some the other, or whether to allow both.
No matter how it goes from the input stage, the next stage is to feed these into build items, so that consumers don't actually care where they came from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 I will rework this PR starting tomorrow so we have something more concrete to comment on 😊
@@ -54,6 +58,9 @@ public static void main(String... args) throws Exception { | |||
classesRoot = new File(args[0]); | |||
wiringDir = new File(args[1]); | |||
cacheDir = new File(args[2]); | |||
group = args[3]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like we shouldn't be passing this in this way; the input should simply be the build configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that this is not cool, but I am not clear on how to pass the build configuration to the runtime runner
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "normal" approach would be to rely 100% on the configuration value and use a config root whose visibility is BUILD_AND_RUN_TIME_FIXED
. However as discussed above, this wouldn't suffice in the case where no value was given and the default has to be computed.
So, we have to bring it in some other way. There are a few possibilities off the top of my head:
- Produce a resource that contains the application name & version and load it at boot using a static init build step
- Put it in a MANIFEST.MF property and load it at boot using a static init build step
- Just generate a class with fields containing the name and version, hard-coded to the computed name and version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is exactly the info I needed to close the loop, thank you! Now everything makes sense. I hadn't seen the any relevant parts of the code so I didn't know how to handle such cases, but with the explanation you just provided plus the information from the other comment I see the way forward.
I'll pick this up again tomorrow most likely and come up with proper solution that adheres to these guidelines.
Thanks for taking the time to explain!
@@ -84,6 +85,11 @@ public BuildResult run() throws Exception { | |||
.addInitial(LaunchModeBuildItem.class) | |||
.addInitial(AdditionalApplicationArchiveBuildItem.class) | |||
.addInitial(ExtensionClassLoaderBuildItem.class); | |||
|
|||
if (!applicationInfo.isUnset()) { | |||
chainBuilder.addInitial(ApplicationInfoBuildItem.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could just as well be produced from a build step which consumes the ApplicationConfig
object.
@@ -103,6 +109,11 @@ public BuildResult run() throws Exception { | |||
.produce(new ShutdownContextBuildItem()) | |||
.produce(new LaunchModeBuildItem(launchMode)) | |||
.produce(new ExtensionClassLoaderBuildItem(classLoader)); | |||
|
|||
if (!applicationInfo.isUnset()) { | |||
execBuilder.produce(new ApplicationInfoBuildItem(applicationInfo)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
@dmlloyd I pushed a completely revised version. It should be simpler and move inline with the internal Quarkus philosophy ( I hope :) ). The names are probably bad, since I am pretty terrible at naming... |
a687249
to
81d61b6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The passing of values through a properties file isn't quite what I had in mind, but it's OK because we don't really have anything better at the moment. I'll take on an issue to improve that.
Pending CI. |
@dmlloyd Just out of curiosity, what do you have in mind as far as improvements go? |
I've opened #1693 with more info on that. |
Cool |
The native test seems to be failing with:
in This seems pretty weird... Is there anything that you see that I have missed @dmlloyd ? |
Yes, I see the bug. The config class is in the deployment module but it has a run time retention. Since you're using build items anyway, the config scope for that |
This allows users to set a desired name for the applications (using quarkus.application.name) or version. The idea came from: quarkusio#1300 (comment) and this configuration is meant to be used by extensions that for some reason need this information (like the planned kubernetes extension)
Thanks! PR updated |
This allows users to set a desired name for the applications
(using quarkus.application.name) or version.
The idea came from:
#1300 (comment)
and this configuration is meant to be used by extensions that for some
reason need this information (like the planned kubernetes extension, where we need to inject something like
ApplicationConfig
in the processor)Implementation notes:
I am not really sure if this is the simplest solution - it kind of seems like I went overboard...
The idea is to inject an
ApplicationInfoBuildItem
that has the default values, use that inConfigurationSetup#initializeConfiguration
to create a newConfigSource
with the default values.This new source has a lower ordinal that the
application.properties
source and thus if values are set there (or in any of the sources with even higher ordinal), those values will be used.If there is a simpler solution for creating the
ApplicationConfig
and populating it from with the values from the build, I'd love to hear it and implement it :)