It appears I am experiencing a ClassLoader bug within Gradle. Any help resolving this would be greatly appreciated.
Original Project
The original project with the issue can be found at pivotalsoftware/pivotal-cla/tree/bug-staging. This project is quite a bit bigger than most would care to debug, so I created a minimal project to reproduce the problem.
Minimal Project
I have produces a minimal sample project that reproduces the issue. See rwinch/gradle-buildscript-question
My original project used the cloudfoundry-gradle-plugin. However, I wanted to simplify the problem for analysis. The sample I provided has a very simple plugin (still named cloudfoundry) that applies a task that doesn’t actually do anything. To run the sample you must first install into maven local using:
$ cd plugin
$ ./gradlew install
When using the plugin as shown below I get the ClassLoading issue.
build.gradle
buildscript {
ext {
tomcatPluginVersion = '2.2.4'
cfPluginVersion = 'testing'
}
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
classpath("com.bmuschko:gradle-tomcat-plugin:$tomcatPluginVersion")
classpath("org.cloudfoundry:cf-gradle-plugin:${cfPluginVersion}")
}
}
apply from: 'gradle/staging.gradle'
gradle/staging.gradle
import org.cloudfoundry.gradle.tasks.*
buildscript {
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
classpath("com.bmuschko:gradle-tomcat-plugin:$tomcatPluginVersion")
classpath("org.cloudfoundry:cf-gradle-plugin:${cfPluginVersion}")
}
}
apply plugin: 'cloudfoundry'
task(bug, type: CreateServiceCloudFoundryTask) {
cloudfoundry {
services {
[
"my-p-mysql" {
label = "p-mysql"
plan = "100mb"
}
]
}
}
}
Invoking the task produces:
$ cd useplugin
$ ./gradlew bug --stacktrace
:bug FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':bug'.
> No signature of method: org.cloudfoundry.gradle.tasks.ServiceCloudFoundryHelper$_createServices_closure1.doCall() is applicable for argument types: (org.cloudfoundry.gradle.CloudFoundryServiceExtension) values: [org.cloudfoundry.gradle.CloudFoundryServiceExtension@81c5da9]
Possible solutions: doCall(org.cloudfoundry.gradle.CloudFoundryServiceExtension), findAll(), findAll(), isCase(java.lang.Object), isCase(java.lang.Object)
The following classes appear as argument class and as parameter class, but are defined by different class loader:
org.cloudfoundry.gradle.CloudFoundryServiceExtension (defined by 'org.gradle.api.internal.initialization.loadercache.DefaultClassLoaderCache$HashedMutableURLClassLoader@585427e' and 'org.gradle.api.internal.initialization.loadercache.DefaultClassLoaderCache$HashedMutableURLClassLoader@4b1c84a9')
If one of the method suggestions matches the method you wanted to call,
then check your class loader setup.
* Try:
Run with --info or --debug option to get more log output.
* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':bug'.
...
Caused by: groovy.lang.MissingMethodException: No signature of method: org.cloudfoundry.gradle.tasks.ServiceCloudFoundryHelper$_createServices_closure1.doCall() is applicable for argument types: (org.cloudfoundry.gradle.CloudFoundryServiceExtension) values: [org.cloudfoundry.gradle.CloudFoundryServiceExtension@81c5da9]
Possible solutions: doCall(org.cloudfoundry.gradle.CloudFoundryServiceExtension), findAll(), findAll(), isCase(java.lang.Object), isCase(java.lang.Object)
The following classes appear as argument class and as parameter class, but are defined by different class loader:
org.cloudfoundry.gradle.CloudFoundryServiceExtension (defined by 'org.gradle.api.internal.initialization.loadercache.DefaultClassLoaderCache$HashedMutableURLClassLoader@585427e' and 'org.gradle.api.internal.initialization.loadercache.DefaultClassLoaderCache$HashedMutableURLClassLoader@4b1c84a9')
If one of the method suggestions matches the method you wanted to call,
then check your class loader setup.
at org.cloudfoundry.gradle.tasks.ServiceCloudFoundryHelper.createServices(ServiceCloudFoundryHelper.groovy:23)
at org.cloudfoundry.gradle.tasks.CreateServiceCloudFoundryTask$_createService_closure1.doCall(CreateServiceCloudFoundryTask.groovy:46)
at org.cloudfoundry.gradle.tasks.CreateServiceCloudFoundryTask.withCloudFoundryClient(CreateServiceCloudFoundryTask.groovy:36)
at org.cloudfoundry.gradle.tasks.CreateServiceCloudFoundryTask.createService(CreateServiceCloudFoundryTask.groovy:45)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:228)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:221)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:210)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:585)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:568)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
... 68 more
(Sometimes) working around the issue
I was able to find a few workarounds for the minimal sample I provided. Unfortuantely, I have not yet found a solution that works for the real project.
Consistent buildscript classpath
If the buildscript classpath in the imported gradle script matches the main build.gradle classpath the issue goes away. You can find an examplef of this in the fix-matching-classpath branch. Specifically, I can add the following to the staging.gradle file to work around the issue:
classpath("com.bmuschko:gradle-tomcat-plugin:$tomcatPluginVersion")
Apply Plugin Class (not string)
Alternatively, applying the plugin class seems to work for the minimal sample (but not my real sample). You can find a sample of this in the fix-plugin-class branch. Specifically I can use the following in staging.gradle file:
apply plugin: org.cloudfoundry.gradle.CloudFoundryPlugin
Help Please
Is this a known bug? I wasn’t able to find one reported.
Any suggestions on how to resolve my problem for the original project?
Cheers,
Rob