Dependency substitution wrong with more than one sub-project with same name?

Good/Bad otherwise I have mult-project build that has ‘leaf’ projects that have the same name; but whose gradle path is distinct.

Further I have a composite sub-project that uses/depends on same named sub-projects.

Like this:

:sub-1:common

:sub-1:sub-a:common

:sub-1:sub-a:war

So :sub-1:sub-a:war depends on both :sub-1:common and :sub-1:sub-a:common.

However, gradle substitutes :sub-1:sub-a:common in for :sub-1:common.

Short of getting rid of same named leaf sub-projects (and/or changing some deps…) is there anyway to work around this?

Assume gradle 2.x and I am build java & ee projects and the 2 common projects make jars that have different archive names.

Multiple sub projects with the same name should be fine so long as their path is unique. However, in this case if you are building a war, you can’t obviously have multiple files in your ‘lib’ directory with the same name. If the naming scheme of your JARs is simply name-version.jar then clearly you will be trying to put two common-version.jar files in your ‘lib’ dir.

yeah so the 2 common subs do indeed have unique fully qualified gradle paths.

And both of the commons sub-projects actually make jars with really different names (i.e. i have unique ‘archivesBaseName’ set in both)

Having said this, running ‘gradle dependencies’ in the war the resulting output comes right out says it is subing one common for the other.

It even prints the FQ gradle path while stating that it is substituting.

So even if there was an assembly time collision of files going into WEB-INF/lib, I would have expected gradle to not perform a substitution evaluating the dependency.

Can you share the output of ‘gradle dependencies’. I’m not aware of a scenario that would cause Gradle to deconflict project dependencies.

Here is the information:

1.The folder structure in question is this (every leaf subfolder has its own build.gradle file):

ICS
+---demand
|
 +---ear
|
 +---ejb
|
 +---icdmatch-jar
|
 +---jar
|
 +---ui-jar
|
 \---war
+---fp
|
 +---account
|
 |
 +---ear
|
 |
 \---ejb
|
 +---common-jar
|
 +---customer
|
 |
 +---ear
|
 |
 \---ejb
|
 \---txn
|
     +---ear
|
     \---ejb
+---jar
+---savings
|
 +---ear
|
 +---ejb
|
 +---icsmatch-jar
|
 +---savingscommon-jar
|
 +---savingsui-jar
|
 \---war
\---tar

2.The project with failing dependency from that folder is

:ics:demand:icdmatch-jar

3.The dependencies output for the icdmatch-jar is here:

https://gist.github.com/nskmda/8f281e3522ef56642e86

Please, make a note about the line #79:

+--- project :ics:demand:jar -> project :ics:jar (*)

this basically overrides local dependency with the one in the parent directory (see folders structure)

The Gradle dependency declaration for the icdmatch-jar is like this (in fact, it’s the full build file):

apply plugin: 'java'
  archivesBaseName = 'icdmatch'
  dependencies {
   compile project(':common')
   compile project(':ics:jar')
   compile project(':ics:demand:jar')
   compile project(':conecommon')
}

As soon as the ics/demand/jar gets renamed into ics/demand/common-jar the build goes through.

Please also note in the directory structure above we had to use savingscommon-jar instead of plain jar because of similar dependency issue (and compilation error) with a project in the ics/savings folder

And, of course settings.gradle file lists all the projects needed in the absolute format (e.g., :ics:demand:war)

Thanks to my colleague for collecting that information!!!

As he was preparing that; I wanted to dis-associate our stuff from the problem…

Here is a GitHub project with a sample: https://github.com/fwelland/Submarine

So the problem is there – but during the forum exchange we had earlier – I began to wonder if the group value was part of the ingredients used during dependency evaluation.

We publish to a private nexus and our artifacts belong to the same group (or so was the plan).

You’ll see our sample root build, sets that group for all subs.

Comment this line out, everything is OK; leave it in – that is when the chaos begins.

As you see, each build does make a distinct artifact jar file.

So maybe the inferred sub-project name (at leaf) + the group name is not unique and that is cause the substitution issue???

Not clear if this is the right or wrong thing for gradle to do, but it is unexpected.

Fred, is correct. This is indeed what seems to be happening. Internally Gradle is using group + name to determine that a particular module is unique. In this case, if all your subproject share a group then you will have to give them a unique name, simply making the jar name unique is not sufficient.

So on my side I have some options to work-around this or otherwise just deal with it.

However, I am curious is gradle doing a ‘good’ or ‘correct’ thing in this case?

I’m not sure it is necessarily either of those things. The main motivation behind this is for compatibility when publishing. Since project dependencies get converted to module dependencies in generated pom files, we internally key off group:name since that will be the value in the pom.