Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support projects with same name but different project paths #108

Closed
tg-freigmbh opened this issue May 22, 2024 · 7 comments · Fixed by #143
Closed

Support projects with same name but different project paths #108

tg-freigmbh opened this issue May 22, 2024 · 7 comments · Fixed by #143
Labels
a:enhancement New feature or request

Comments

@tg-freigmbh
Copy link

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?

@jjohannes jjohannes self-assigned this May 23, 2024
@jjohannes jjohannes added the a:enhancement New feature or request label May 23, 2024
@jjohannes
Copy link
Member

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.

@jjohannes jjohannes changed the title Duplicate key Exception when using Projects with the same name [Maybe] Support projects with same name but different project paths May 23, 2024
@tg-freigmbh
Copy link
Author

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?

@jjohannes
Copy link
Member

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.

@tg-freigmbh
Copy link
Author

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.

@jjohannes
Copy link
Member

jjohannes commented Oct 11, 2024

Need to figure out if implementing #136 would be good enough to solve this as well.

@jjohannes jjohannes changed the title [Maybe] Support projects with same name but different project paths Support projects with same name but different project paths Nov 4, 2024
@jjohannes
Copy link
Member

@tg-freigmbh this is now supported when using the settings plugin on top of Gradle's normal include("...") (since 1.8). For example, you can do something like this:

include(":app1:feature1:data")
include(":app1:feature2:data")
            
rootProject.children.forEach { appContainer ->
    appContainer.children.forEach { featureContainer ->
        featureContainer.children.forEach { module ->
            javaModules.module(module) {
               group = "org.example" // this configuration block is optional
            }
        }
    }
}

Please let me know, if this is not sufficiently resolving the issue.

@tg-freigmbh
Copy link
Author

looks great so far, I will give feedback when I have some time refactoring the build

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants