This message was deleted.
# configuration-cache
s
This message was deleted.
f
Whenever you use a build service you have to make sure that it is wrapped in a
BuildServiceProvider
or Gradle will try to serialize it. The easiest way in a task to achieve this is:
Copy code
class MyTask : DefaultTask() {
  lateinit var srv: Provider<MyService>
}

val srvProvider = gradle.shared...registerIfAbsent...

tasks.withType<MyTask>().configureEach {
  srv = srvProvider
  usesService(srvProvider)
}
Obviously both
lateinit
and
var
look ugly and might be misused, an alternative:
Copy code
abstract class MyTask : DefaultTask() {
  abstract val srv: Property<Provider<MyService>>
}

val srvProvider = gradle.shared...registerIfAbsent...

tasks.withType<MyTask>().configureEach {
  srv.value(srvProvider).finalizeValue()
  usesService(srvProvider)
}
UNTESTED!
n
I tried both of these approaches and I get the same error in both cases…
It still tries to serialize it
BuildServiceProvider
itself has the following code:
Copy code
// TODO:configuration-cache - complain when used at configuration time, except when opted in to this
@SuppressWarnings("rawtypes")
public class BuildServiceProvider<T extends BuildService<P>, P extends BuildServiceParameters> extends AbstractMinimalProvider<T> implements Managed {
f
What we've been doing was casting what is returned from
registerIfAbsent
to an actual
BuildServiceProvider
of the correct type. This allowed us to pass them on to worker actions. Maybe the same hack is necessary for configuration cache compatibility?
Copy code
class MyBuildService : BuildService<MyBuildService.Parameters> {
  interface Parameters
}

typealias MyBuildServiceProvider = BuildServiceProvider<MyBuildService, MyBuildService.Parameters>

@Suppress("UNCHECKED_CAST")
val myServiceProvider = gradle.shared...registerIfAbsent... as MyBuildServiceProvider

class MyTask : DefaultTask() {
  val myBuildService: Property<MyBuildServiceProvider>
}
Again UNTESTED and written from the top of my head.
n
That doesn’t seem to work either for me:
Copy code
Could not determine the dependencies of task ':services:notifications:notifications-dao:generateJooq'.
> Could not create task ':services:notifications:notifications-dao:migrateDbTask'.
   > Cannot set the value of task ':services:notifications:notifications-dao:migrateDbTask' property 'postgres' of type org.gradle.api.services.internal.BuildServiceProvider using a provider of type com.paxos.gradle.EmbeddedPostgresService.
f
Well, the
EmbeddedPostgresService
is not a
BuildServiceProvider
, what is it?
n
I have a
Provider<EmbeddedPostgresService>
from
registerIfAbsent
that I am casting to
Provider<BuildServiceProvider<EmbeddedPostgresService, EmbeddedPostgresService.Params>>
f
You need to cast it to
BuildServiceProvider<EmbeddedPostgresService, EmbeddedPostgresService.Params>
without the surrounding
Provider
. The signature of
registerIfAbsent
claims to return a plain
Provider
but it actually returns a
BuildServiceProvider
.
n
BINGO! success. Thank you very much @Fleshgrinder
f
🙂
n
I can’t help feeling this should have been documented somewhere….
f
What I don't understand is why it does not work without the cast. There should be some
instanceof
check somewhere for this, and that should evaluate to true as long as nobody turns that original
Provider
into something else.