Gradle-launcher-1.12-rc-1.jar not on classpath

Some classes that would in the tooling-api jar in previous versions are now in the launcher jar. Yet the launcher jar is not on the classpath when using the gradleApi() as a dependency. This is causing NoClassDefFoundError exceptions. E.g. if I add gradleApi() I can not access org.gradle.launcher.GradleMain. Admittedly I’m most interested in org.gradle.tooling.internal.impl.DefaultGradleProject which is used from the tooling API.

For background, it appears that some of the new module loading in 1.12 is missing some connections. ToolingRegistratonAction.execute is being called in my IDE, which results in a NoClassDefFoundError for DefaultGradleProject. It looks like ToolingRegistrationAction (from gradle-tooling.jar) uses the class GradleProjectBuilder class that is in gradle-ide.jar, but that class uses DefaultGradleProject from the gradle-launcher.jar, which is no longer in the classpath. I believe the DefaultGradleProject class was in the tooling-api jar before and now appears to be in the launcher jar, yet the launcher jar is not in my classpath in 1.12-rc-1. Hence the JVM can’t load ToolingRegistrationAction. Seems the new module loading logic isn’t matching actual dependencies. Radim, it looks like you were specifically trying to get around this in commit 876ebfe.

What are you actually doing that’s failing? Have you got a stack trace?

I see that another post covered the same issue, and described it better than me: http://issues.gradle.org//browse/GRADLE-3068

We’ve been using the GradleLauncher (internal, I know) to great success for a while now. And one key that kept it easy to use was a line like this:

((DefaultGradle) launcher.gradle).getServices().get(BuildClassLoaderRegistry).addRootClassLoader(getClass().classLoader)

That line lets the launcher run with our current testRuntime classpath, which simplifies the buildscript. In 1.12-rc-1 the root class loader is now immutable, and there doesn’t seem to be any opportunity to add our classloader before the script is processed. I can sorta get around that problem. We then run the project’s execute() and run into GRADLE-3068

Ok, thanks. This should be working again. Can you try out 1.12-rc-2?

I have the same issue. Can’t find BuildClassLoaderRegistry. What should I use instead?

gradle.services.get(BuildClassLoaderRegistry).addRootClassLoader(getClass().classLoader)

According to Adam’s comment above, this should be working again in 1.12. Is that not what you are seeing?

No. According to this changeset the class was removed by Luke and Adam. http://code-review.gradle.org/changelog/Gradle?cs=cdada17c6308956cf5ec84845a63a1856e9252ea

I believe the comment Adam made above was for DefaultGradleProject class, not BuildClassLoaderRegistry

Probably time to switch from ‘GradleLauncher’ (which was deprecated and later made internal) to using the Gradle tooling API.

how to run the configuration phase with the tooling api since there is no getBuildAndRunAnalysis() method for BuildLauncher.

pass --dry-run?

That sounds like a good option.

How would I add a classloader to the BuildLauncher, to achieve the samething as

gradle.services.get(BuildClassLoaderRegistry).addRootClassLoader(getClass().classLoader)

Further, I need to prevent the GradleConnector from trying to acquire a distribution. For my purposes the distribution is already in the calling classloader.

The tooling api does not offer the same flexibility. I think it should provide parity with GradleLauncher before the classes are removed.

@Pablo:

regarding…

How would I add a classloader to the BuildLauncher, to achieve the same thing as ‘gradle.services.get(BuildClassLoaderRegistry).addRootClassLoader(getClass().classLoader)’

This was private API and has been removed. What’s the use case you are trying to support?

@Luke

We build our own Gradle distribution extended with our own plugins. As part of the build, we run unit tests that launch individual builds using Spock framework. Hence the need to use a classloader to run with in-memory distribution vs. an outside distribution.

We won’t be able to upgrade until we find a way to do this. Any suggestions?

The ‘BuildLauncher’ is not available anymore but you can use the tooling API instead. If you need to add classes to its classpath, you might want to explore adding them as part of your init script. You can point the ‘GradleConnector’ to the distribution you want to use on your local disk.

Point is that its an embedded distribution (in developement). What we need is better test harness for plugin development since most folks have used BuildLauncher for this purpose.

Peter commente on this post that there would be better test support coming. http://forums.gradle.org/gradle/topics/how_to_execute_a_task_in_a_plugin_test_build

Sorry I meant to say GradleLauncher in my previous comment.

Test support in Gradle core might still take a while but you can try the nebula-test plugin from Netflix.