The documentation for custom tasks just uses a private field and setter/getter combination for task properties. But the JavaExec task in gradle source code uses Property<String> for the mainClass task property (https://github.com/gradle/gradle/blob/f8d612ca6b1d21f79690800ceaf95c97b10ba0ac/subprojects/language-java/src/main/java/org/gradle/api/tasks/JavaExec.java#L114). What’s the advantage here? Should Property<T> be used for custom tasks?
Property and Provider allow for lazy configuration whereby build authors can configure the source of the property before the actual value itself is known/configured.
You could support both styles of configuration with a convenience setter method
public class MyTask extends DefaultTask {
@Input
private final Property<String> property = getProject().getObjects().property(String)
public Property getProperty() {
return this.property;
}
public void setProperty(String value) {
getProperty().set(value);
}
@TaskAction
public void doStuff() {
String propertyValue = property.get();
// do stuff with propertyValue
}
}
I’m not 100% sure if this is good advice, because this would violate the java beans spec (since the getter and setter are different types) which might confuse groovy
In Groovy, setters and getters can differ in type. This is perfectly legal and Groovy will handle it:
- When you use it as a setter, like,
property = 'mystring',setProperty(String)is called. - When you use it as a getter, like,
println(property),getProperty()with thePropertyreturn type is called.
However:
- It can lead to type confusion. Someone reading your code might expect the property to always be a
String. For different types, it could be better to call the function differently. - I know the name of the property is irrelevant for this example, but just to clarify, I don’t recommend using names like
property,getProperty,setProperty, because it can confuse the reader, as theDefaultTaskclass already has the following functions:
public Object property(String propertyName) throws MissingPropertyException {
return super.property(propertyName);
}
public boolean hasProperty(String propertyName) {
return super.hasProperty(propertyName);
}
public void setProperty(String name, Object value) {
super.setProperty(name, value);
}
I think “property” in the example was more a placeholder for any property name.
And besides that, you should never add such convenience setter and getter methods nowadays anyway.
Just expose the property and that’s it like:
public abstract class MyTask extends DefaultTask {
@Input
public abstract Property<String> getProperty();
@TaskAction
public void doStuff() {
String propertyValue = property.get();
// do stuff with propertyValue
}
}
(of course “property” is still a placeholder for a better name)
I totally agree with that, and I just wanted to say the same, just as others already pointed out:
The best way to create a property is I think to use an abstract class, just as you described:
Those “others” are also me ![]()