Dependency resolution constraints from maven pom artifacts without the java plugin?


I’ve been struggling to understand this for a while now… and failed. I see some kind of internal resolution mechanism that makes a project with the java plugin applied automatically add constraints from maven pom files down in the dependency tree. It’s best explained on an example. Consider this short project:

plugins {
  // id("java-library")

repositories { mavenCentral() }
configurations { foo }

dependencies {
  foo "com.fasterxml.jackson.core:jackson-databind:2.15.2"
  foo "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.1"

Note the two dependencies with different versions. If you apply the ‘base’ plugin only, configuration foo resolves to (irrelevant details omitted):

+--- com.fasterxml.jackson.core:jackson-databind:2.15.2
|    +--- com.fasterxml.jackson.core:jackson-annotations:2.15.2
|    |    \--- com.fasterxml.jackson:jackson-bom:2.15.2
\--- com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.1

However, if you apply the java plugin (and leave everything else as it was), version constraints are imported and added from the jackson-bom subproject, leading to consistent versions everywhere else:

+--- com.fasterxml.jackson.core:jackson-databind:2.15.2
|    +--- com.fasterxml.jackson.core:jackson-annotations:2.15.2
|    |    \--- com.fasterxml.jackson:jackson-bom:2.15.2
|    |         +--- com.fasterxml.jackson.core:jackson-annotations:2.15.2 (c)
|    |         +--- com.fasterxml.jackson.core:jackson-core:2.15.2 (c)
|    |         +--- com.fasterxml.jackson.core:jackson-databind:2.15.2 (c)
|    |         \--- com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2 (c)
\--- com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.1 -> 2.15.2

Note the constraint nodes in the above: “(c)”. I’m puzzled and wonder if somebody could enlighten me as to:

  1. where is the resolution/ constraint-adding mechanism in gradle code? I’ve been digging through it for hours now but couldn’t find it.
  2. is it possible at all to configure the base project to add those constraints (without applying the java-library plugin)? I experimented with adding the exact same attributes to the foo configuration which I saw injected by the java plugin but this doesn’t seem related (and in fact causes resolution to fail).

Thank you!

You don’t need the java-library plugin, the jvm-ecosystem plugin is enough.
Is it acceptable to apply that, or does it really have to be just base?

The difference is, that com.fasterxml.jackson:jackson-bom does not have a Gradle Module Metadata file, but only the BOM POM.

The jvm-ecosystem plugin does only three things:

  • it adds the sourceSets container
  • it adds the two JVM-specific attributes to the attribute scheme for which you probably got an exception in your trying as you probably did not define the attributes yourself
  • it configures a variant derivation strategy that for example defines how variants are derived from POM files without Gradle Module Metadata files

The last point is the relevant one.
Without this configuration, the BOM is not recognized as BOM and thus no constraints are used.
So if you really need to use just the base plugin, you could for example use a component metadata rule to ad-hoc fix the variant, so that it is properly recognized as platform.

Thank you for spending your time replying, @Vampire ! It is the last bullet point I couldn’t find among gradle’s sources - your pointer is very helpful.

So if you really need to use just the base plugin, you could for example use a component metadata rule to ad-hoc fix the variant, so that it is properly recognized as platform

It’s actually more complicated - I have a multi-module project (quite complex) where two modules were consuming the same input configuration(s) - everything was identical but one of them was a Java project, the other was a base project and the outputs of those configurations resolved to a different set of artifacts (because of constraints and version alignment). I saw the constraints in the dependency dump, I just couldn’t figure out how they’re automagically added for Maven POMs (these occur in dependencies of dependencies, they are not referenced directly as a platform).