What's the benefit of using the Gradle Property type in a Gradle plugin oppose to just using String type for example?
Asked Answered
M

1

8
  1. In a Gradle plugin I could define my properties as:
open class ExamplePluginExtension {

    var exampleName: String? = null

}

And accessing it in build.gradle.kts like so:

example {

    exampleName = "Lorem Ipsum"

}

Or 2. I can use the Property type of Gradle (org.gradle.api.provider.Property):

open class ExamplePluginExtension @Inject constructor(objectFactory: ObjectFactory) {

    val exampleName: Property<String> = objectFactory.property(String::class.java)

}

Accessing it in build.gradle.kts like so:

example {

    exampleName.set("Lorem Ipsum")

}

The Gradle documentation promotes the use of the Property type in Gradle Plugins, but why? The use of the Property type is quite a hassle, creates a lot of boilerplate and disables the use of nullable properties. I see many third-party libraries such as Flyway use the first option, completely ignoring the Property type.

Mohun answered 11/1, 2022 at 16:30 Comment(0)
C
1

The primary benefit of properties, as I understand it, is lazy configuration (if used correctly). They also let you define conventional values, even based on other providers, meaning the conventional value can be computed lazily as well. And there's also the benefit of the API provided by Property. That includes methods like isPresent and getOrElse that let you handle an unset property with no conventional value. Note there are also more specialized types of properties, such as ListProperty and DirectoryProperty, which add more methods.

It's not that much more verbose to use properties, or at least it isn't anymore. You are injecting the object factory and creating the property manually. But you can just let Gradle create and decorate the extension (or task) class for you. It could look something like:

import org.gradle.api.provider.Property

abstract class ExamplePluginExtension {

     abstract val exampleName: Property<String>

     init {
         // There's an overload that accepts a Provider. Note it might 
         // be better to do this in the plugin class after creating the
         // extension, not sure).
         exampleName.convention("default name")
     }
}

Or as an interface:

import org.gradle.api.provider.Property

interface ExamplePluginExtension {

    // If you want to set the conventional value, then you'd have to set it
    // somewhere else (e.g., in the plugin class after creating the extension).
    val exampleName: Property<String>
}

Then you'd register the extension:

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.*

class ExamplePlugin : Plugin<Project> {

    override fun apply(project: Project) {
        // this returns an instance of the extension class
        project.extensions.create("example", ExamplePluginExtension::class)
    }
}

Which would let you do the following in a build file:

plugins {
    // apply example plugin
}

example {
    exampleName = "Foo"
}
Cown answered 29/11, 2023 at 2:15 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.