Hello. I been having problems integrating a custom Shared Build Service that I want to use to provide custom dependency injection to my plugin project using java.
I’m following this wiki https://docs.gradle.org/current/userguide/build_services.html
Here is my code:
Shared Build Service - DependencyInjection.java
public abstract class DependencyInjection implements BuildService<DependencyInjection.Params>{
interface Params extends BuildServiceParameters {
Property<Injector> getDependencyInjector();
}
private final Injector injector;
public DependencyInjection(){
injector = getParameters().getDependencyInjector().get();
}
public Injector getInjector(){
return injector;
}
}
Plugin - FooPlugin.java
public class FooPlugin implements Plugin<Project> {
public void apply(Project project) {
//create provider with the injector and register module
Provider<DependencyInjection> serviceProvider = project.getGradle().getSharedServices().registerIfAbsent("di", DependencyInjection.class,
spec -> spec.getParameters().getDependencyInjector().set(createDependencyInjector())
);
// Register a task
project.getTasks().register("barTask", BarTask.class, task ->{
task.getDI().set(serviceProvider);
});
}
private Injector createDependencyInjector(){
return Guice.createInjector(new PluginModule());
}
}
Custom Task - BarTask.java
public abstract class BarTask extends DefaultTask {
private final Logger logger = getLogger();
@Internal
public abstract Property<DependencyInjection> getDI();
@TaskAction
public void processTask() {
logger.quiet("Processing Task");
Injector injector = getDI().get().getInjector();
try{
Awesome awesome = injector.getInstance(Awesome.class);
awesome.dance();
}catch(Exception e){
logger.error(e.getMessage());
}
}
}
Build Gradle - build.gradle
tasks.register('customBarTask', org.me.BarTask) {
doFirst {
println("Hello World!")
}
}
One of my problems is in the initialization and registry of the custom Shared Build Service with my project. when running my task in gradle ./gradlew barTask
I get this error.
Execution failed for task ':barTask'.
> Failed to query the value of task ':barTask' property 'DI'.
> Could not isolate value org.me.DependencyInjection$Params_Decorated@39952730 of type DependencyInjection.Params
> Could not serialize value of type InjectorImpl
This happens when I’m trying to use the Provider created from the registry of the service. <Provider>.get()
.
As a work around I removed the BuildServiceParameters in my Shared Build Service.
Modified Shared Build Service - DependencyInjection.java
public abstract class DependencyInjection implements BuildService<BuildServiceParameters.None>{
private final Injector injector;
public DependencyInjection(){
injector = Guice.createInjector(new PluginModule());
}
public Injector getInjector(){
return injector;
}
}
And removed the configuration of the Shared Build Service in the plugin file FooPlugin.java
...
//create provider with the injector and register module
Provider<DependencyInjection> serviceProvider = project.getGradle().getSharedServices().registerIfAbsent("di", DependencyInjection.class,
spec -> {}
);
...
With this, now running my task ./gradlew barTask
works fine.
Now the problem is that, If I want to run my custom task from the gradle.build file ./gradlew customBarTask
I get this error:
Execution failed for task ':customBarTask'.
> Cannot query the value of task ':customBarTask' property 'DI' because it has no value available.
So, finally, as a work around for that, I created a private function in my task file BarTask.java to initialize the shared build service in the task class like this.
public abstract class BarTask extends DefaultTask {
private final Logger logger = getLogger();
// I changed this as well
@Internal
private final Provider<DependencyInjection> di = getInjectorService();
@TaskAction
public void processTask() {
logger.quiet("Processing Task");
//This also change
Injector injector = di.get().getInjector();
try{
Awesome awesome = injector.getInstance(Awesome.class);
awesome.dance();
}catch(Exception e){
logger.error(e.getMessage());
}
}
@SuppressWarnings("unchecked")
private Provider<DependencyInjection> getInjectorService(){
return (Provider<DependencyInjection>)getProject()
.getGradle()
.getSharedServices()
.getRegistrations()
.findByName("di")
.getService();
}
}
I also removed the configuration of the task from the plugin class FooPlugin.java
...
// Register a task
project.getTasks().register("barTask", BarTask.class, task ->{});
}
...
With that everything works now.
I’m not sure if I’m missing something. I only want to be able to provide this resource “Custom Dependency Injection” to my task files.
Any help will be appreciated.
Thanks