General Gradle classpath questions

Hi. I’ve just created a problem topic about jettyRun and the classpath. I also had similar problems with the tomcat-gradle-plugin, and there the author seems to be starting his own classloader to explicitly filter out Gradle’s jars. Yet somewhere else I read some words from the Kotlin plugin’s author that he has similar problems. I will be giving a presentation on Gradle at my company next week, and we will see if we can start using it (we are now maven 3 and more and more people notice its problems - yes, we are slow). However, we mainly write webapps, and we like to start some containers for our testing during the build. We have had enough classloading issues with groovy, asm, cglib, hibernate, spring, slf4j, logback and so on, so that the last thing we need is hunting ghosts while running tests within Jetty / Tomcat embedded in the build process. I will definitely have to mention that the classpath is somehow wrong.

So, I would like you to answer me a few questions about the classpath, or maybe point me to some documentation so that I can read it myself: 1. There is no possibility to have separate classpaths for plugins / tasks, I can only define script-global classpath libs, correct? Or are these libs build-global, i.e. libraries introduced in the parent module will also be available in the child modules? 2. Do plugin developers (we will have custom plugins) wanting to manage the classpath have to come up with their own ways of forcing loading only the things they need? Just as the tomcat-gradle-plugin author does? 3. Do all plugins have always access to the same global classpath? (This is actually a rewording of the previous two.) Like, the compileJava task having gradle jars on the classpath? Seems not to be the case - why does then the Jetty plugin have the jars in runtime? Why is it different from the Compilation tasks? 4. Is there a standard way plugin authors can add custom classpaths? I am aware that I can add a new configuration, but how difficult is it to fetch its classpath when the task is about to be executed? I guess I have access to Project and can look it up and iterate over the jars, is this correct? Does Gradle download jars from such custom configurations or do plugin developers have to explicitly trigger it? 5. Is this by design that, apparently, the classpath is per-script and tasks see it as well? Are there plans to change it? I think this is one area where maven is much better - I have classpath per goal. For example, why would the jetty plugin or whatever know about some ssh jars that are in the build classpath only because I deploy via ssh?

wujek

  1. There is no possibility to have separate classpaths for plugins / tasks, I can only define script-global classpath libs, correct? Or are these libs build-global, i.e. libraries introduced in the parent module will also be available in the child modules?

Each project has a separate build script classpath, and the root project’s classpath is inherited by the children as their classloader is a child of the root project’s class loader.

  1. Do plugin developers (we will have custom plugins) wanting to manage the classpath have to come up with their own ways of forcing loading only the things they need? Just as the tomcat-gradle-plugin author does?

At the moment, yes.

  1. Do all plugins have always access to the same global classpath? (This is actually a rewording of the previous two.) Like, the compileJava task having gradle jars on the classpath? Seems not to be the case - why does then the Jetty plugin have the jars in runtime? Why is it different from the Compilation tasks?

I don’t understand the question.

  1. Is there a standard way plugin authors can add custom classpaths? I am aware that I can add a new configuration, but how difficult is it to fetch its classpath when the task is about to be executed? I guess I have access to Project and can look it up and iterate over the jars, is this correct? Does Gradle download jars from such custom configurations or do plugin developers have to explicitly trigger it?

Have a look at the checkstyle and findbugs plugins in the core for how this is done. It’s not as hard as what you might think.

  1. Is this by design that, apparently, the classpath is per-script and tasks see it as well? Are there plans to change it? I think this is one area where maven is much better - I have classpath per goal. For example, why would the jetty plugin or whatever know about some ssh jars that are in the build classpath only because I deploy via ssh?

The intention is to isolate plugins in terms of internal dependencies. This will happen at some point.

Thanks for the answers. In #3 i was asking whether all tasks have the whole Project classpath available, including the compileJava task. For example, I don’t have ant jars as compile dependencies, but I can access them in my classes because Gradle has them. But I checked it and it is not the case - for compilation I have only what I want to have. However, certain tasks do have Gradle jars (jetty, tomcat, …). I guess the issue is whether the task forks a new JVM or not. AFAIK Jetty / Tomcat don’t fork, that’s why they have gradle libs in cp, whereas JavaCompile / GroovyCompile does fork, and that’s why it is much easier to influence the cp.

The difference is not the forking (‘JavaCompile’ doesn’t even fork by default), but the design and implementation of the tasks and their underlying libraries. The compile class path passed to a compiler and its execution class path are two different things.

Right, thanks. I will have to look into classpath management for tasks / plugin in more detail, as Luke has already mentioned. Thanks to both of you.