Custom plugin - extending Exec class

I’m working on a custom plugin which has a task. This task is basically an exec task but with some preconfigured values to make things easier. Since it’s essentially an Exec task I’d like to be able to extend the Exec class and just take into account whatever custom configuration I have from my plugins Convention object. However I’m running into some issues because I can’t override the exec method (which is also the TaskAction) since it’s package private. I was hoping to simply override it and do some custom stuff in the overridden method and then just call the super.exec(). Since this isn’t possible, I tried another approach which was to just set the Exec tasks commandLine and arg properties in the constructor of my task. The problem with this is that the convention object hasn’t been populated at this point. Below is roughly what I have.

Plugin class:

class FooPlugin implements Plugin<Project> {
        void apply(Project project) {
                                def javaConvention = project.convention.plugins.java
            def classpath = (javaConvention == null) ? null : javaConvention.sourceSets.main.runtimeClasspath
        project.convention.plugins.foo = new FooPluginConvention(classpath)
                 project.task('fooStart', type: FooStartTask)
        }
                                       }
                                                                                           class FooPluginConvention {
              FileCollection classpath
      FooPluginConvention(String classpath) {
        this.classpath = classpath
    }
      }

Task class:

class FooStartTask extends Exec {
    FooStartTask() {
        def settings = project.convention.plugins.foo
        executable
= "/bin/foo"
        args settings.classpath
    }
}

So, the problem here is that “classpath” on the FooPluginConvention object hasn’t been initialized yet. How would I go about doing this?

It might be better not to extend ‘Exec’ but to model your task’s API explicitly. In the task action you can then delegate to ‘project.exec’.

Instead of the convention object, you should use an extension object. (See the Gradle User Guide for more information.)

1 Like

Ok that makes sense. However I’m still not clear on what you are referring to by project.exec. Is that simply some exec task that I would create and then invoke from my task action?

Thanks

‘project.exec’ is a method on the ‘Project’ class that offers the exact same API as the ‘Exec’ task.

That’s perfect. Thanks for the help.

Fantastic! I went looking for something like this a while ago and gave up! FYI As far as I could tell, this is not yet documented anywhere publicly.

The ‘project.exec’ method is documented in the Gradle Build Language Reference.