Does the java-platform plugin support the import scope?

I love the new BOM support in Gradle 5, but there’s one issue I’m having while attempting to create a bill of materials with the java-platform plugin. I can successfully create a BOM for dependencies, but I’m unable to include another BOM with the import scope. I have created a sample project at https://github.com/budjb/gradle-import-test to demonstrate what happens. I’d expect that the POM includes the dependency with the “import” scope, but it’s including it with the “compile” scope.

Does the plugin support this and I just need to change my code, or is this a missing feature? I wanted to ask before I submitted an issue on GitHub.

Did you ever find anything out about this?

I had a need to research this myself a while back. Here’s what I bookmarked then:

Here’s a relevant 2012 comment by Gradle dev @Peter_Niederwieser:

I did figure it out! You need to allow dependencies as the documentation describes, and include the platform dependency outside of the constraints block. Build the bom and inspect it after that change, and it looks as expected.

The solution you describe is not reflected in the example repository you linked earlier, so I’ll post it just for the record:

plugins {
    id 'java-platform'
    id 'maven-publish'
}

javaPlatform.allowDependencies()
dependencies {
    api platform("org.springframework.boot:spring-boot-dependencies:2.1.4")
    constraints {
        api 'commons-logging:commons-logging:1.2'
    }
}
publishing {
    publications {
        library(MavenPublication) {
            from components.javaPlatform
        }
    }
}

Also there’s a interesting thing you can do in multimodule builds, if your base project is a java-platform you may import that in your subprojects:

dependencies {
    implementation platform(project(':'))
}

@budjb and @geissld: Have you ever managed to override a dependency from the imported BOM within the platform project?

I’ve tried several things, like

dependencies {
    api(platform("org.springframework.boot:spring-boot-dependencies:3.2.3"))

    constraints {
        api("com.h2database:h2:2.1.214")
    }
}

or

dependencies {
    api(platform("org.springframework.boot:spring-boot-dependencies:3.2.3"))

    constraints {
        api("com.h2database:h2") {
            version { strictly("2.1.214") }
        }
    }
}

or

dependencies {
    api(platform("org.springframework.boot:spring-boot-dependencies:3.2.3") {
        constraints {
            api("com.h2database:h2") {
                version { strictly("2.1.214") }
            }
        }
    })

    constraints {
        // ...
    }
}

But none is working.

I like the approach to import the Spring Boot BOM in your own platform project and prefer it over the io.spring.dependency-management plugin.

Can you provide a more complete example of what you mean or at least a build --scan?
If I use your second example or the short-hand notation of it using !!, I get the expected result.
Are you sure you do not apply the Spring Dependency Management plugin anymore?
Because using it, overrides strict versions in a not too transparent way which is one reason why using it is a bad idea.

I’ve just created a demonstrator project, and indeed, the second approach works fine:

./gradlew -q app:dependencies --configuration runtimeClasspath  

------------------------------------------------------------
Project ':app'
------------------------------------------------------------

runtimeClasspath - Runtime classpath of source set 'main'.
+--- project :dependencies
|    +--- org.springframework.boot:spring-boot-dependencies:3.2.3
|    |    +--- com.h2database:h2:2.2.224 -> 2.1.214 (c)
|    |    \--- org.apache.commons:commons-lang3:3.13.0 (c)
|    +--- com.h2database:h2:{strictly 2.1.214} -> 2.1.214 (c)
|    \--- org.apache.commons:commons-text:1.11.0 (c)
+--- org.apache.commons:commons-text -> 1.11.0
|    \--- org.apache.commons:commons-lang3:3.13.0
+--- project :utilities
|    \--- project :list
\--- com.h2database:h2 -> 2.1.214

(c) - A dependency constraint, not a dependency. The dependency affected by the constraint occurs elsewhere in the tree.
A web-based, searchable dependency report is available by adding the --scan option.

And I’ve found the issue in my setup! In one of the subprojects, I had an unnecessary dependency of implementation(enforcedPlatform("org.springframework.boot:spring-boot-dependencies")), which overrode the overridden constraint.

1 Like

Great. :slight_smile:
Yeah, strict version constraints and thus also enforcedPlatforms should be used very conservatively.
Actually, I wonder that it did not fail with the two conflicting strict version constraints on the same dependency.