This message was deleted.
# community-support
s
This message was deleted.
g
So, what's best? Converting
val developers
type and get rid of
ListProperty
, instantiating a new instance myself with
action.execute(object : Developer)
or switch the plugin extension from
interface
to
abstract/open class
?
t
Are you using a precompiled script plugin? If so I think this is due to either
objects
and/or
Developer
interface. For
objects
, inject an
ObjectFactory
inside your plugin and pass it to your extension. For
Developers
I think you'd have to move it to its own
*.kt
file (as a rule of thumb, any class that's part of your API should live in its own
*.kt
or
*.java
rather than in the
*.gradle.kts
of your precompiled script plugin)
v
You don't need to give the
ObjectFactory
from the plugin to the extension, I think you can also directly let Gradle inject the
ObjectFactory
to the extension. You might also consider using a
DomainObjectSet<Developer>
instead of a
ListProperty<Developer>
.
👍 2
t
Ah yes, indeed, you can inject into the extension directly (I'm doing just this myself in my plugins 🤦) (I also though about
DomainObjectSet<Deleveloper>
but never used it myself; also it's a
Set
, not a `List`; there's
NamedDomainObjectList
too, but then it's "named")
v
Non-set variant would be
DomainObjectCollection<Developer>
I think, unless it should be named objects, then of course
Named...
g
yes, it's a precompiled script plugin
I noticed Gradle provides/injects the
ObjectFactory
automatically
I think you'd have to move it to its own
*.kt
file (as a rule of thumb, any class that's part of your API should live in its own
*.kt
or
*.java
rather than in the
*.gradle.kts
of your precompiled script plugin)
Ok, I'll do it
v
It does not (inject). By using just
objects
you do use
project.getObjects()
which then causes the problem of "capturing project". By injecting it into your extension you get a reference that does not need to capture
project
to be used.
g
to inject I do need a (abstract) class, don't I?
v
No, you can also do
@get:Inject val objects: ObjectFactory
in an interface
g
nice
when I try to configure the organization in my
build.gradle.kts
script by calling the respective
organization { }
DSL, which is
Copy code
val organization: Property<Organization>

fun organization(action: Action<Organization>) = action.execute(organization.get())
I get > Cannot query the value of extension 'scijava' property 'organization' because it has no value available. Because
organization
hasn't been yet instantiated by Gradle At this point, I guess I can only switch the extension to a class and manually instantiate that by
objects.newInstance<>(()
or do I have another choice?
v
Is the user expected to be able to set a complete own organization? If not but he is only expected to configure the one organization, it does not make much sense to have a
Property<Organization>
A
Property
only makes sense for values that are expected to be set, so that you can wire them together and lazily get the set value. But if it is always the one same organization, there is absolutely no need to use a
Property
, it only makes the API needlessly more complex.
g
the user is expected to set a complete organization, name and url
v
Just to be sure, do you mean "set a complete organization instance" like
organization = Organization(...)
or do you mean just "set all fields for the organization" like
organization { ... }
g
I mean, the user is supposed to call the
organization
dsl and set all of its field
I'm writing the plugin in a way that every "setting error" gets properly detected and notified, that is, if
organization
hasnt been called and if any of the field hasnt been set
v
Well, then you don't have a problem, do you? You only get the mentioned error when the user tries to configure the orgainzation before he has set it. If you want to allow first configuring then setting it, you could just remember the Action and apply it later instead of instantly applying it.
g
I'm doing in a way that calling the
organization
DSL construct will automatically use
objects
to instantiate the
Property<Organization>
v
But you said the user is expected to set it. Why doing it implicitly if the user is supposed to set it. You will also have the "problem", that if someone does
organization { ... }
and then
organization = ...
the first will be discarded if that is a problem.
g
I meant to set it implicitly by calling the corresponding DSL
v
But you only set it once and the user just configures it using
organization { ... }
, right?
g
I can push so you can take a look at what I meant
v
I think I know what you meant. The question is just, is it expected that the user can also do
organization = ...
or is the user only expected to do
organization { ... }
g
ah, I got what you mean
that's an interesting question, I'd guess only the latter
v
Then as I said, it probably does not make sense to have
Property<Organization>
at all, but simply have an
Organization
field. And then when you add the extension in your plugin, there use
objects.newInstance<Organization>()
to create the organization and set the field.
or maybe better indeed make it an abstract class and set it through the constructor, then it can be a
val
which is better as it should not be changed.
You can either create the new instance within the constructor, or create it in the plugin and give the instance to the constructor