Could not find implementation class for plugin error when using Gradle 4.1+

plugins

(PA) #1

Hello,

I’m trying to develop a gradle plugin and running into some issues. This is my first attempt at developing a gradle plugin and I’m still learning following Gradle’s user guides. I seem to be having some problem depending on what version of Gradle I use. I’m hoping you can help me with this and tell me if I’m doing something wrong or if there’s a bug on latest/newer versions of Gradle.

First, I have my plugin source like this:
File path: gradle-plugin\src\main\groovy\com\my\org\gradle\mytool\plugins
File content:

package com.my.org.gradle.mytool.plugins

import org.gradle.api.Plugin
import org.gradle.api.Project

class  HelloPlugin implements Plugin<Project> {
    Project project
    
    void apply(Project project) {
       project.task('demo') << {
            println "hi!"
        } 
    }
}

I then added a plugin id through the resource file named "my-plugin.properties"
File path: gradle-plugin\src\main\resources\META-INF\gradle-plugins
File content:
implementation-class=com.my.org.gradle.mytool.plugins.HelloPlugin
I then added a unit test for this plugin using Spock
File path: gradle-plugin\src\test\groovy\com\my\org\gradle\mytool\MyPluginSpec.groovy
File content:

package com.my.org.gradle.mytool.tests

import spock.lang.*

import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.GradleRunner
import org.junit.Rule
import org.junit.rules.TemporaryFolder

import static org.gradle.testkit.runner.TaskOutcome.*

class MyPluginSpec extends Specification {

    @Rule
	final TemporaryFolder testProjectDir = new TemporaryFolder()
    
    
    def "test the demo task" () {
        given:
            //copy some files from "gradle-plugin/test-resource" directory that contains a build.gradle file and applies the plugin as "apply plugin: 'my-plugin'"
        when:
            Run a gradle build using Gradle testkit
        then:
            //capture the output of the build and validate that the demo task worked.
    }
}

My main build.gradle file for building this project looks like this:

apply plugin: 'java-gradle-plugin'
apply plugin: 'groovy'

dependencies {
    compile gradleApi()
    compile 'org.codehaus.groovy:groovy-all:2.4.4'
    compile 'org.gitlab4j:gitlab4j-api:4.6.0'
    
    testCompile gradleTestKit()

    testCompile('org.spockframework:spock-core:1.1-groovy-2.4') {
        exclude module: 'groovy-all'
    }
    testCompile 'org.codehaus.groovy:groovy-all:2.4.4'
    
    testRuntime ('com.athaydes:spock-reports:1.2.7') {
        exclude module: 'groovy-all'
    }
}

If I run the build using Gradle 2.11 version, compilation and the unit test is successful. If I use Gradle 4.1 or 4.2, I need to update my main build.gradle script so that it uses Groovy 2.4.11; otherwise I get errors about wrong groovy being loaded. So, I update it like this:

apply plugin: 'java-gradle-plugin'
apply plugin: 'groovy'

dependencies {
    compile gradleApi()
    compile 'org.codehaus.groovy:groovy-all:2.4.11'
    compile 'org.gitlab4j:gitlab4j-api:4.6.0'
    
    testCompile gradleTestKit()

    testCompile('org.spockframework:spock-core:1.1-groovy-2.4') {
        exclude module: 'groovy-all'
    }
    testCompile 'org.codehaus.groovy:groovy-all:2.4.11'
    
    testRuntime ('com.athaydes:spock-reports:1.2.7') {
        exclude module: 'groovy-all'
    }
}

Now, when I run the build using Gradle 4.1 or 4.2, I get an error with following message about the plugin implementation class is not able to load the class that it’s referring to.


    * What went wrong:
    A problem occurred evaluating root project 'junit7340673529257668127'.
    > Could not find implementation class 'com.my.org.gradle.mytool.plugins.HelloPlugin' for plugin 'my-plugin' specified in file:/Users/projects/gradle-plugin/build/resources/main/META-INF/gradle-plugins/my-plugin.properties.

(PA) #2

Found out the root cause. In the unit test when I use the testkit to execute a gradle build in an external process, I had the following directories being added in the classpath:

def classDir = [
			new File('bin').absolutePath,
			new File('build/classes/main').absolutePath,
			new File('build/resources/main').absolutePath
		]

I needed to add new File('build/classes/groovy/main').absolutePath to that list. After this, using Gradle 4.1 when I run the build, the unit test no longer throws class not found exception.


(Benjamin Muschko) #3

To inject the plugin classpath you should use GradleRunner.withPluginClasspath(). For a more detailed discussion please see the “Testing Gradle plugin” guide.


(PA) #4

Thanks for your suggestion. I’m trying to follow the entire guide and all of the recommendations as part of this development exercise. I haven’t been able to get the withPluginClasspath() working yet, but I’m going to get back to it again.