I’m working on building a custom gradle plugin that cobbles a bunch of my favorite other plugins together for a micro service framework I own. Right now I’m trying to customize the ApplicationPlugin with a customStartScript.
In the service using my plugin I have something that looks like this:
plugins {
id "com.plugin"
}
service {
mainClass = "com.thing.MainClass"
}
In my custom plugin I have code that looks like this:
project.getTasks().register(CUSTOM_START_SCRIPT_TASK_NAME, CreateStartScripts.class, (task)->{
ServiceConfiguration service = (ServiceConfiguration) project.getExtensions().getByName("service");
task.setMainClassName(service.mainClass);
}
The issue is that service.mainClass is null when I debug. I’m assuming that if I could set the mainclass on the JavaApplicationPlugin convention that might do the work for me, but I can’t work out how wire up the providers to do that.
Assuming service.mainClass is a Property<String>, then your plugin can establish a default value by linking the application.mainClass and service.mainClass properties using:
YourServiceExtension sE = project.getExtensions().create("service", YourServiceExtension.class);
project.getExtensions().getByType(JavaApplication.class)
.getMainClass().convention(sE.getMainClass());
This is definitely the type of direction I was looking for. My ServiceConfiguration is a bean, I’m not really sure how to wire up the Property correctly.
I have something like this:
import org.gradle.api.provider.Property;
public class ServiceConfiguration {
public Property<String> mainClass;
}
But when I try to register the extension the value is null.
class ServicePlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
ServiceConfiguration serviceConfiguration = project.getExtensions().create("service", ServiceConfiguration.class);
project.getExtensions().getByType(JavaApplication.class).getMainClass().convention(serviceConfiguration.mainClass);
}
}
I’m clearly missing a step here. This is how I’m registering the plugin.
Your plugin is not creating an instance of Property<String> and assigning it to mainClass. There’s a few ways you could do this, but my recommendation is that you take advantage of Gradle’s “managed properties”. To do this change your ServiceConfiguration class to:
public abstract class ServiceConfiguration {
public abstract Property<String> getMainClass();
}
When you then use this type for creating your extension, Gradle will generate a concrete class with the necessary implementation. You then pass convention the result of getMainClass(). Note, you do not need a setter, the property should be “final” and builds will change the value stored in the property instance, not change the property reference in the extension.