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


(Justin Ryan) #1

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.


(Adam Murdoch) #2

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


(Justin Ryan) #3

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


(Adam Murdoch) #4

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


(Pablo Munoz) #5

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

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


(Peter Niederwieser) #6

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


(Pablo Munoz) #7

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


(Pablo Munoz) #8

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


(Peter Niederwieser) #9

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


(Pablo Munoz) #10

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

pass --dry-run?


(Peter Niederwieser) #11

That sounds like a good option.


(Pablo Munoz) #12

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.


(Luke Daley) #13

@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?


(Pablo Munoz) #14

@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.


(Pablo Munoz) #15

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


(Benjamin Muschko) #16

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.


(Pablo Munoz) #17

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.


(Pablo Munoz) #18

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


(Pablo Munoz) #19

Sorry I meant to say GradleLauncher in my previous comment.


(Benjamin Muschko) #20

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