This message was deleted.
# plugin-development
s
This message was deleted.
p
If you have one containter instance that you wish to expose via extension and shared service, put the instance in the shared service, and reference it from the extension. Your extension may receive the shared service via @ServiceReference injection, and your extension accessor may delegate to the shared service accessor.
k
I'm using a version of Gradle predating
@ServiceReference
. Is there anything special that would need to be accounted for?
Also, do I have this right, then:
Copy code
interface MyExtension {
    val service: Property<MyService>
    val servers
        get() = service.get().servers
}

abstract class MyService: BuildService<BuildServiceParameters.None> {
    abstract val servers: NamedDomainObjectContainer<MyInstanceInfo>
    
     fun getClient(name: String): MyClient? { ... }
}
In versions of Gradle with
@ServiceReference
,
MyExtension.service
would just be a
Provider<MyService>
annotated with
@ServiceReference
? What about versions of Gradle predating
@ServiceReference
?
p
Yes, in Gradle 8 you would just annotate service's getter with a @ServiceReference, and that would work like @Inject. I am not experienced with build services before Gradle 8. AFAIK, one must use a BuildServiceRegistry, which is available via Gradle instance, to acquire the service instance.
k
The docs were kind of confusing as it relates to manual use of
Task.usesService()
and the like, creating the impression that more hoops were needed. Something like
Copy code
tasks.withType<MyTask>().configureEach {
  client.set(project.the<MyExtension>().getClient("myClient"))
  usesService(project.the<MyExtension>().service)
}
The other thing is wrt `MyExtension.servers`; this kind of implies that I am forcibly creating the service during configuration time, which seems off, but I don't know of any suitable workaround if that were the case.
p
I suppose that in current Gradle the general style is to return properties and providers, instead of instances, so that you propagate the lazyness as much as you can. So that
servers
would return something like
service.map { it.servers }
k
Right, but the whole idea from the user's standpoint would be
Copy code
configure<MyExtension> {
  servers.register("myClient") { ... }
}
So the link has to be broken somewhere. This is the whole idea behind sharing a
NamedDomainObjectProvider
between a service and an extension.
p
True. In that case, it seems appropriate to instantiate the build service. The lazyness in this case would happen at the next layer -- the user would call these methods inside a configuration closure or something like that.
The service must be instantiated sooner or later, after all.
If this is innapropriate, maybe you should create the
NamedDomainObjectProvider
in your
Plugin.apply
method, and explicity "inject" this object into both the extension and the service.