Clashing artifacts


(Devin Smith) #1

I’ve got a couple of external dependencies whose names are “poorly” chosen. For example:

implementation ‘com.XYZ:core:1.0.0’
implementation ‘com.ABC:core:1.0.0’

When it comes time to package up a distribution, the classpath is constructed by copying all of the artifacts to a single directory. Unfortunately, this leads to the artifact name ‘core-1.0.0.jar’ clashing.

It seems like flat classpaths for distributions are the opinionated standard. In theory though, the classpath doesn’t need to be a flat directory. Arguably, we could preserve the uniqueness much the same way that artifact repositories store the data (directory per package name hierarchy). Is there any way to have the Distribution plugin maintain uniqueness by structuring the classpath through a directory hierarchy?

Alternatively, is there a way to rename the artifacts? Specifically, smooshing the groups names into something like ‘com.XYZ.core-1.0.0.jar’ vs ‘com.ABC.core-1.0.0.jar’.

Thanks!


(James Justinic) #2

Most definitely as there are ways to both access the details of the resolved artifacts and influence the file names upon inclusion in the distribution. While you could gain enough to make the file names unique from the full source artifact path, matching the files up gives you a bit more control in exactly what you want to use to build the new file name. It’s not exactly pretty, but it would give you the group name in front:

distributions {
    main {
        contents {
            eachFile { FileCopyDetails fileCopyDetails ->
                configurations.runtimeClasspath.resolvedConfiguration.resolvedArtifacts.findAll { fileCopyDetails.file == it.file }.each {
                    fileCopyDetails.name = "${it.moduleVersion.id.group}.${fileCopyDetails.name}"
                }
            }
        }
    }
}


(Devin Smith) #3

Great, thanks for the info! I think this will work for me when I’m controlling the distribution.

When I’m publishing my artifacts for consumption by others though, it seems like they will be responsible for “fixing” the name (depending on if they use a flat directory for classpath jars).

Is there a way to transparently repackage the artifacts into a new artifact namespace (leaving java namespace the same). IE: provide com.mycompany.repackaged:com-xyz-core:1.0.0, com.mycompany.repackaged:com-abc-core:1.0.0? In this way, those that depend on my artifacts won’t have to deal with “fixing” the name.


(James Justinic) #4

Nothing stops you from creating a project that does nothing more than resolve the dependency and republish under your own group / artifact name. However, since it would now be possible to have both your repackaged library and the original (of one of them) on the classpath, you could get unintended behavior if the versions are different. At that point, it’d probably be most consumption-friendly if you just used something like the Shadow plugin and bundled / relocated them in your library or a single dependency with the problematic artifact contents.