gradlex-org/java-module-dependencies

[Maybe] Support projects with same name but different project paths

Opened this issue · 4 comments

I get this stacktrace:
{code}
Caused by: java.lang.IllegalStateException: Duplicate key Localization (attempted merging values UMS and UMS.Utilities)
at org.gradlex.javamodule.dependencies.JavaModuleDependenciesExtension.lambda$create$14(JavaModuleDependenciesExtension.java:216)
at org.gradle.api.internal.provider.DefaultProvider.calculateOwnValue(DefaultProvider.java:72)
at org.gradle.api.internal.provider.AbstractMinimalProvider.calculateValue(AbstractMinimalProvider.java:115)
at org.gradle.api.internal.provider.TransformBackedProvider.calculateOwnValue(TransformBackedProvider.java:81)
at org.gradle.api.internal.provider.AbstractMinimalProvider.calculateValue(AbstractMinimalProvider.java:115)
at org.gradle.api.internal.provider.Collectors$ElementFromProvider.collectEntries(Collectors.java:100)
at org.gradle.api.internal.provider.Collectors$TypedCollector.collectEntries(Collectors.java:334)
at org.gradle.api.internal.provider.Collectors$TypedCollector.collectInto(Collectors.java:329)
at org.gradle.api.internal.collections.AbstractIterationOrderRetainingElementSource$Element.realize(AbstractIterationOrderRetainingElementSource.java:345)
at org.gradle.api.internal.collections.AbstractIterationOrderRetainingElementSource.realizePending(AbstractIterationOrderRetainingElementSource.java:142)
at org.gradle.api.internal.DefaultDomainObjectCollection.addEagerAction(DefaultDomainObjectCollection.java:224)
at org.gradle.api.internal.DefaultDomainObjectCollection.all(DefaultDomainObjectCollection.java:142)
at org.gradle.api.internal.CompositeDomainObjectSet.addCollection(CompositeDomainObjectSet.java:114)
at org.gradle.api.internal.CompositeDomainObjectSet.create(CompositeDomainObjectSet.java:58)
at org.gradle.api.internal.collections.DefaultDomainObjectCollectionFactory.newDomainObjectSet(DefaultDomainObjectCollectionFactory.java:112)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.initAllDependencies(DefaultConfiguration.java:961)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.getAllDependencies(DefaultConfiguration.java:946)
at org.gradle.api.internal.artifacts.configurations.DefaultUnlockedConfiguration_Decorated.getAllDependencies(Unknown Source)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.initAllDependencies(DefaultConfiguration.java:963)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.getAllDependencies(DefaultConfiguration.java:946)
at org.gradle.api.internal.artifacts.configurations.DefaultUnlockedConfiguration_Decorated.getAllDependencies(Unknown Source)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.hasDependencies(DefaultConfiguration.java:954)
at org.gradle.api.internal.artifacts.ivyservice.ShortCircuitEmptyConfigurationResolver.resolveGraph(ShortCircuitEmptyConfigurationResolver.java:85)
at org.gradle.api.internal.artifacts.ivyservice.ErrorHandlingConfigurationResolver.resolveGraph(ErrorHandlingConfigurationResolver.java:77)
... 177 more
{code}
My Project names are not unique, basically there is a Project :Server:Localization :Client:Localization, :Installer:Localization, ...

Soo I assume its basically not possible to use this plugin under these circumstances?

Yes your assumption is correct. Right now, the plugin does not support such setups. The project name of each subproject needs to be unique and match the (last part) of the Module Name in the module-info.java file.

The setup of using hierarchies like you do is also slightly discouraged in Gradle as I perceive it. There are more issues you could run in with other Gradle functionality (like this long standing issue/discussion).

My recommendation for projects is to always use uniques names for the logical project name, while keeping the physical location as it is. In your example this would mean defining projects like this:

include(":server-localization")
project(":server-localization").projectDir = file("Server/Localization")
include(":client-localization")
project(":client-localization").projectDir = file("Client/Localization")
include(":installer-localization")
project(":installer-localization").projectDir = file("Installer/Localization")

And the module-info.java files would have names like:

module com.mycompany.myproduct.server.localization {
}
module com.mycompany.myproduct.client.localization {
}
module com.mycompany.myproduct.installer.localization {
}

If for some reason you need/want to keep the setup with the project hierarchies and duplicated names, I would be open to extend the plugin to use the "subproject path" instead of just the "subproject name" in the mapping of "Module Name" to "Subproject". If that can be added without breaking existing functionality.

Ok. I am currently migrating existing sources to gradle from the bottom up. So I somewhat have to keep existing structures and modulenames (even if they are stupid/nonconsistent), because consumers that have not been migrated yet expect them to be that way, I can give your recommendation a try.
Another suggestion/ticket, maybe for another ticket
I can manually specify moduleNamToGa, which is really helpful. Wouldnt it be possible to manually specify moduleNameToProjectPaths or something similar?

You can already use moduleNamToGa for local projects. For that it is required to add this to settings.gradle:

includeBuild(".")

Then you can also address local projects by group:name notation. Then, If all you Localization projects have different groups, you can configure things like this:

javaModuleDependencies {
    moduleNameToGA.put("com.my.server.loc", "my.server:Localization") // 'my.server' defined by `group = "my.server"`
}

This would already work, if you won't get the exception before.

If you want, you can try it by building this plugin from source.
(clones this repo; and then add pluginManagement { includeBuild("path-to-local-clone") } to your settings)

And adjust this line here such that it skips duplicate instead of failing:
https://github.com/gradlex-org/java-module-dependencies/blob/main/src/main/java/org/gradlex/javamodule/dependencies/JavaModuleDependenciesExtension.java#L217

Maybe that can be a "good enough" solution for you. I am happy to accept a PR with such a change.

Thanks for the merge, I think this issue can be closed.
I was not aware of the project isolation feature, but you are right, in that case another solution is needed.