Trying to figure out how to use a ServiceReference...
# community-support
a
Trying to figure out how to use a ServiceReference as an Input to a task. Ideally this is a service set up once to be shared among all projects in the build.
Copy code
@ServiceReference(value = "infoService")
  @Optional
  abstract Property<InfoService> getInfoService();

  @Input
  @Optional
  public Map<String, Info> getInfo() {
    if (!getInfoService().isPresent()) {
      return null;
    }
    return getInfoService().get().getInfo();
  }
Are service references not supposed to be inputs? Or is the
@ServiceReference
annotation just not ideal for this?
I should add that this InfoService is obtained from another plugin that is meant to be instantiated once in a single project shared across all other projects in the build
Or is the alternative of 1. Create a single MapString, Info property in the root project (or buildsrc) 2. Inject that via pluginExtension to each project a more idiomatic approach?
v
Never tried, but I guess you should make
getInfo
a
MapProperty
and then set it to
getInfoService().map(InfoSerivce::getInfo)
a
Well I guess what the fundamental question is, what's the best way to share a large chunk of data among projects? Is this approach resonable? I can switch it to mapProperty
v
A shared build service is a good way to share data between projects, yes
a
kk, and sorry I guess a data mismatch issue here. BuildService.map(MapX,Y) returns
Provider<Map...>
not a
MapProperty
and I always have trouble moving between those two
I Guess the @Input type could just be Provider<Map> instead
v
MapProvider, not Provider<Map>
a
I might be missing something here, the error I see is that the result of
getInfoService.map(InfoService::getInfo)
returns a
Provider<Map<String, Info>>
. But is that because my InfoService is misconfigured (returning Map, instead of MapProvider)? or something?
looks like I have to create an intermediate MapProperty from Objectfatory and then assign the result to that
ah so I need the build service to use MapProperty throughout to allow for configuration caching when I do this anyway
sorry just thinking out loud here, I think I have it all figured out, thanks for the guidance
v
You would of course not calculate the property in the getter, that is doing the opposite of what the whole `Property`/`Provider` API is for.
Just make the getter abstract so that Gradle implements it for you you properly and where you register the task (or if you must in its constructor) set the value. The
MapProperty
can be set from a
Provider<Map>
.
a
So this InfoService is optional and registered by another plugin. I'm not sure I can set it during register. It's possible I'm overcomplicating this. Plugin A: register
InfoService
based on user provided values Plugin B -> task B: consume
InfoService
if available (and treat as input).
It doesn't seem like I can query the sharedbuildregistry lazily to optionally obtain the service without dealing with a
UnknownDomainObjectException
on a call to
project.gradle.sharedServices.registrations.named
v
Why should you? You got a provider, mapping it is lazy.
a
oh maybe I don't understand when the
UnknownDomainObjectException
is thrown
v
I meant why should you need to query the build registry or stuff
a
To set the map property at task registration?