I’ve spend quite some time to get a solution on this issue, unfortunately until now I failed. I am using Gradle 1.8 and my situation is as follows:
I have several multi-project builds (Java) with each one having dependencies to sub-projects within the same project, builds from other Gradle projects (= Jar files) and external Java libs. For example, project A is a multi-project with the sub-projects A1 and A2. A1 depends on A2 and A2 on a sub-project B1 of a different Gradle project B. The sub-project B1 itsself depends on external Java libraries such as JUnit or SQL Driver etc… (external Java libraries may apply in each of my Gradle projects).
What I need is to control the ordering of the classpath in each sub-project, since any sub-project may overwrite (=patch) a class from any of my Gradle projects. For example, sub-project A2 may redefine a class that is initially defined in sub-project B1. Or sub-project B1 may redfine a class that is initially defined in project C and project C is a dependency of project A and B.
So, the classpath of any of my Gradle projects should look like this:
the build (=Jar file) of the current sub-project,
Builds (=Jars) of all Gradle projects that are a dependency to the current one,
the external Java libraries that are dependencies in the current sub-project and any of the Gradle projects referenced by the current one.
How do I achieve this? Any help is really appreciated!
Gradle doesn’t give strong guarantees about the ordering of a configuration’s elements, and I’m not aware of an easy way to achieve what you are asking for. Instead I’d try not to rely on class path ordering, which is a very brittle solution anyway.
Thanks for your reply, Peter. So, am I right that Gradle will not resolve the correct classpath at all times when a project redefines a class of a depending project?
For example: project A depends on project B and C. Project B depends on project C and redefines a class of project C. For the classpath of project A it would be crucial, that project C is after project B, i.e.: A;B;C
There is no single correct way to do this. It’s a matter of if and how class path ordering is defined, and Gradle doesn’t give any strong guarantees about it. I would expect that the order of direct dependencies (as listed in the ‘dependencies’ block) is maintained. If you need more than that, you could perhaps implement a lazy ‘org.gradle.api.file.FileCollection’ that wraps around ‘org.gradle.api.artifacts.Configuration’ and sorts elements as desired.
Hm, okay, I was hoping that it would not be necessary to modify Gradle sources, since this means that we will have to implement this in future Gradle releases my company might use for maintaining our Java projects with Gradle.
As for the classpath ordering, the important thing for us is that class patching works, although we would like to get rid of it in the long-term. The impression I have from several tests is that things don’t work when having transitive dependencies as described in my above example. I thought, a way to solve this could have been by using different configurations and redefining some of the Gradle variables like
You can do this without modifying Gradle sources. You might have to use some Gradle internals, though (not sure).
As I said, there is no single “right” class path order when transitive dependencies are involved, since there is more than one way to linearize a (dependency) graph. Gradle doesn’t give any guarantees about this. If you do want to rely on transitive class path ordering, you’ll have to sort the artifacts yourself. Since this is best done lazily (i.e. only when needed), the idea to implement your own ‘FileCollection’ came to mind. I don’t see how your problem can be solved solely by using different configurations and setting variables such as ‘compileClasspath’, but then I may not fully understand your requirements.
perhaps I did not get the point on how to implement a FileCollection lazily without modiffying Gradle source. Could you help me with an example or documentation on this topic?
You could implement the ‘FileCollection’ interface yourself, perhaps with a class that delegates to another file collection (or configuration) but returns an iterator that sorts elements as desired. First you’d have to find a way to figure out the desired order, though. As for docs, check out the Javadoc and/or source code.
Remember that I’m just throwing out ideas here. There might be other/better ways to solve your problem, and ultimately only you can decide.
Hello. It was one year ago when this thread born. Are the any news about classpath ordering? I need to bypass the android.jar library with another jar file. In the latter jar file there are java class with same package and class name but some class has different methods from the standard one of android.jar.