Best practice for getting plugin settings into plugin

I have developed a small plugin for our group, and everything works well. However, I found the configuration of the plugin a bit cumbersome, and I am thinking perhaps I have missed some best practice.

In my “build.gradle” I have something like this:

apply plugin: 'sonic'
  ...
   sonic {
    containerName = 'OurContainer'
}

Then, in my plugin code, developed as a separate project, I have the following:

project.extensions.sonic = new SonicPluginExtension()
class SonicPluginExtension {
    def containerName = null
    def sonic(Closure closure) {
        closure.delegate = this
        closure()
    }
}
  ...
  project.task('sonicimportservicetypes', type: ServiceTypeImportTask) {
    sonicContainerName = { project.sonic.sonicContainerName }
}

What bothers me with the above is the closure around the “project.sonic.sonicContainerName” in the task configuration. It took me a while to figure out that it was required. I have found no easier way to make sure the configuration is delayed to the right moment, is this really the best way of doing it? It seems a little bit too indirect.

At first I naively thought that the build.gradle would have been read when the plugin code was read, but that doesn’t seem to be the case, hence my indirect reading of the settings via a closure.

Is there an easier/better solution to what I try to accomplish?

Correctly handling evaluation order is the main challenge when writing plugins. How to best do this depends, among other things, on how ‘ServiceTypeImportTask’ is implemented. If it allows you to pass a closure, then I’d stick to that. It won’t get any simpler.

PS: The ‘SonicPluginExtension.sonic’ method is not needed; you should remove it.

Some other minor points…

You should always use ‘extensions.create()’ if you aren’t using an existing object as an extension.

project.extensions.create('sonic', SonicPluginExtension)

You should also prefer ‘project.configrure()’ over manually executing configuration closures…

class SonicPluginExtension {
    def project
    def containerName = null
      SonicPluginExtension(Project project) {
      this.project = project
    }
       def sonic(Closure closure) {
      project.configure(this, closure)
    }
}

However, as Peter said above you don’t need the ‘sonic()’ method in this case. I included it here as an example of how to use ‘project.configure()’.

Thanks for your quick feedback. We’ll stick with this solution, then.