This message was deleted.
# community-support
s
This message was deleted.
s
Generally that would indicate a timing problem
ah yes, if that gets applied in
plugin{}
version has not yet been set
Not sure I believe tht "just broke", but 🤷🏼
The better way is to have your task use Property and use a convention
The convention would be the project's version
e
projevtVersion.set(project.provider { project.version.toString() })
or
.convention
instead of
.set
, as mentioned, but that doesn't change how to postpone the provider
s
yes that works, but providers have certain implications
its similar to a lambda versus method ref
method ref is always going to be better
myTask.getProjectVersion().convention(project.getVersion())
though actually, why do you even set it out of curiosity? a task always has access to the project
ohhhh, and I just realized
it.projectVersion.set(...)
implies it is already a Property I guess
so the convention should already work
but again, why set it?
that's rhetorical 😉
c
Not sure I believe tht "just broke",
Haha, fair enough. I swear it's true though 🙂
why do you even set it out of curiosity? a task always has access to the project
That's a good question. I used to simply reference it for quite a while, no problem. And then gradle started giving me deprecation warnings about how I shouldn't access it directly. This was a while ago so I don't remember exactly.
s
You're task's representation is a String so my exact convention call woud not work. you'd need to map it
but regardless, its all about delaying that
Or you could change the task to
Property<JavaVersion>
Depends on your needs/wishes/deepest-desires
c
projevtVersion.set(project.provider { project.version.toString() })
Oh, that's looks cool. I can create a provider out of anything? And it will only get resolved when the task runs? Perfect. I think that will solve my immediate problem. The question remains though why I had to turn group and version into properties in the first place. I might revert that change and see what gradle has to say.
s
Property is a provider also
I mean do what you want, but you are just creating a completely new unnecessary object with that approach here
And they are Properties (they have been for a LONG time btw) just for this timing issue
c
What are properties? Version? It just says Object in the source code.
s
Think of it like this... 1.
plugins {}
applies your plugin (because that happens very early) 2. your plugin accesses the projects version 3. your script sets the version
c
And what is this convention thing. I have no idea what that is. Googling now...
s
Property
org.gradle.api.provider.Property
org.gradle.api.provider.Provider
is that what you are asking?
c
I know what a provider is, I think. But project.version just say object in the api
(sorry, I'm speaking in kotlin here)
If project.version was a provider, I would have simply written
Copy code
it.projectVersion.set(project.version)
but I can't...
s
Actually, I was wrong... version is a String
I think you just primed my brain to think Property 😄
c
Well, it's probably whatever you assign to it in your script. Which is normally a string, but could be anything.
s
no, i broke point into even before setting it
c
So what does this do...
Copy code
it.projectVersion.convention(project.version.toString())
s
That will not work, you still try to access toString eagerly
c
right
s
you actually will have to do what @ephemient suggested
though, i still say (externally anyay) I am not sure why you set that
just access it when you need it during task exection
unless you allow setting it on the task itself, which seems strange
c
I will try to access group and version directly in the task. If gradle doesn't complain, all good. If it does, I'll use the lambda. Regardless, I learnt something today, so cheers to you both.
s
Well to be clear (we're engineers, we like clear right...) - a Provider != lambda
in terms of correlation
Just look at some of the APIs between Property and Provider and I think it will make sense
c
no, but it accepts a lambda, or a Callable...
Copy code
<T> Provider<T> provider(Callable<T> var1);
s
right but Callable can be a lambda, method ref or anon class
its all about how you use / call it
c
technically correct...the best kind 🙂
s
Not sure about the tecnhincally, but definitely correct 😉
v
and use a convention
Using
convention(...)
or
set(...)
/
value(...)
both is fine. It has different semantics. If later someone does
set(x)
and then
set(null)
, with a
convention(...)
it is effective again, with
set(...)
or
value(...)
it would now be unset.
though actually, why do you even set it out of curiosity? a task always has access to the project
Accessing the
project
during task execution is deprecated as it is incompatible with configuration cache. Besides that it can easily be a task input by having a dedicated property. If you do it like OP wrote, then it is delayed until the task is configured. If you do it with a provider it is delayed until the property is queried, so potentially just at task execution time, so exactly what is needed here.
Or you could change the task to
Property<JavaVersion>
JavaVersion
to set the project version? o_O
Actually, I was wrong... version is a String
... no
s
No? I set a break point valuate getVersion() and it returns me a String
v
Because you set it to a
String
s
Though you def know more than me
c
That's cause you set it to a string
s
no
v
It is
Object
s
thats before i set it to anything
this is in a plugin apply
v
You can set it to anything and thus dynamically calculate a version a bit delayed by doing it in
toString()
of it
s
so no i did not "set it" to anyting
v
Early way of "delayed" calculation before
Property
existed
Yeah, sorry, "someone" set it to a "String"
For example to
"undefined"
which is its default value
Or if you set it via
gradle.properties
which I usually do if I don't need dynamic calculation, then it indeed was you.
s
no, i always do it in my script though not for any particular reason 🙂
v
I often set it in
gradle.properties
and then in the code set
version
to a more capable object, that in its
toString
just returns the version but has additional methods like getting the main release version or determining whether it is a snapshot version, ...
s
Oh wow, that's actually a great idea!
I actually even have such an object
v
I usually do it in
gradle.properties
so that it is set as early as possible for any early consumers and this way it is also reliably set for all projects in the build and an automatic release process also has it easier to increase the version.
c
Accessing the
project
during task execution is deprecated as it is incompatible with configuration cache.
Thanks for the input. I knew I changed it for a reason.
If you do it like OP wrote, then it is delayed until the task is configured
Which was working fine for me until recently. I can shuffle things around and register tasks in
afterEvaluate
but I think the better solution is to delay the reading of group and version until the latest possible.
s
Mine gets calculated in a plugin which I apply first, so what you said it perfct
So basically ignore everything I said and listen to Vampire which is general good advice on here anyway 😉
😄 1
c
I usually do it in
gradle.properties
That's yet another file that defines the build. I even grumble at having to split my GAV up by putting the project 'name' in settings.gradle. Yes, I used to use maven, and the trio were always sitting nicely together at the top of the pom. (I'm sure there are good reasons for the way it works now).
v
and register tasks in
afterEvaluate
Please don't. Any
afterEvaluate
you use should make your heart bleed. It is usually just symptom treatment. The provider is exactly what you want. It maybe as just accidentally that it worked before.
but I think the better solution is to delay the reading of group and version until the latest possible.
Exactly
c
and register tasks in
afterEvaluate
> Please don't
Noted. I will use my new
provider(Callable)
powers to solve all my problems.
v
I even grumble at having to split my GAV up by putting the project 'name' in settings.gradle.
Well, you don't have to split them. You can define your full GAV in the publishing configuration. Using the project group, project version and project name are just the conventions. But Gradle is very flexible and if you want the trio to be together, you are free to do so.
It might prove problematic if you want to use composite builds, though, I'm not fully sure
s
Yes, I used to use maven, and the trio were always sitting nicely together at the top of the pom. (I'm sure there are good reasons for the way it works now).
Did you enjoy duplicating versions everywhere throughout a multi-project build too? 😉
c
You can define your full GAV in the publishing configuration
Right, ok. That trips me out a little. I've always thought of the three as intrinsic to the build. But gradle doesn't care until publishing the jar I suppose. But you do require a settings.gradle don't you?
s
They are intrinsic to the publication
v
By now you require a
settings.gradle
, yes. But you don't need to set a name in it. The default is the directory name, so it usually makes sense to have a name defined in there. But you don't have to.
And
group
indeed is only relevant for publishing. If you don't want to publish or developing an end product, setting the
group
actually is pointless. (Unless some plugin you use thinks it needs it)
Even
version
could be left out if you don't want to publish and are ok with the built artifacts not to have a version in their name for example.
c
great. All good information to have. Thanks @Vampire.
👌 1