Just want to clarify with folks: is it true that i...
# plugin-development
k
Just want to clarify with folks: is it true that it is not possible to create a value source that captures a REST call if the client is not serializable? So, for example:
Copy code
abstract class MyValueSource : ValueSource<String, MyValueSource.Parameters> {
  interface Parameters : ValueSourceParameters {
    abstract val client: Property<MyClient>
    // other stuff
  }
}
Just to clarify, then, that it's generally better to have a client constructed internally rather than have it passed in...?
v
Of course, just think about it. From where do you pass it in? From configuration phase. When does the value source run? The first time before the configuration phase to determine whether to actually execute the configuration phase and then again in case the configuration phase is executed. But for the first execution, the value needs to come from some persistence, so the parameters must be "Gradle serializable".
a
I guess you want to avoid creating a client every time? Rather than creating a client on-demand inside of the ValueSource, you could create a custom service that has a persistent client, and then the service has a function that either returns a ValueSource, or even just a regular Provider.
v
Do you mean to avoid creating the client twice if the value source is run twice, or something else? Also how exactly do you mean that? Wiring the build service to value source parameters? This only will work if the value source is not obtained at configuration time though
k
I'm supposing that it is possible to have something like
Copy code
abstract class MyValueSource : ValueSource<String, MyValueSource.Parameters> {
  @ServiceReference
  abstract val myService: Property<MyService>
  
  private val client = myService.map { ... }
}
so that you have serializable parameters, but 1) does that even work under the hood, and 2) is it possible to do the same without
@ServiceReference
if it did?
v
Copy code
abstract class MyService : BuildService<BuildServiceParameters.None> {
    val client = "client"
}
gradle.sharedServices.registerIfAbsent("myService", MyService::class.java)
abstract class MyValueSource : ValueSource<String, ValueSourceParameters.None> {
    @get:ServiceReference
    abstract val myService: Property<MyService>
    private val client = myService.map { it.client }
    override fun obtain() = client.get()
}
println(providers.of(MyValueSource::class){}.get())
=>
Copy code
Could not create an instance of type Build_gradle$MyValueSource.
> No service of type ObjectFactory available in DefaultServiceRegistry.
But as I said, as long as you do not need the value source value at configuration time, you can supply the build service as parameter. Just when you need the value source at configuration time this will not work.