How to exclude an package from platform dependency

Here is my dependencies in build.gradle.kts:

dependencies {
    implementation(platform("com.alibaba.csp:sentinel-parameter-flow-control")) {
        exclude("com.alibaba.middleware", "metrics-integration")
    }
}

But there is error, says that exclude is not avaiable here.

How cloud I add exclude in implementation(platform(...))?


Here is an example:https://github.com/robberphex/gradle-example

When try to run ./gradlew -q run, it will encounter error:

$ ./gradlew -q run
e: file:///projs/gradle-example/app/build.gradle.kts:11:9: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public fun Configuration.exclude(group: String? = ..., module: String? = ...): Configuration defined in org.gradle.kotlin.dsl

FAILURE: Build failed with an exception.

* Where:
Build file '/projs/gradle-example/app/build.gradle.kts' line: 11

* What went wrong:
Script compilation error:

  Line 11:         exclude("com.alibaba.middleware", "metrics-integration")
                   ^ Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
                       public fun Configuration.exclude(group: String? = ..., module: String? = ...): Configuration defined in org.gradle.kotlin.dsl

1 error

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

BUILD FAILED in 1s

What is your use-case, why should you want to do that?
A platform does not include and dependencies, so there is nothing to exclude.
A platform is only adding version contraints.
And if one of them doesn’t suit you, you can just declare an own version constraint, strict if you want to downgrade a version.

I want to define some dependency in parent module,
and at sub-module, add dependency without version, with exclude.

I don’t really get what you mean or how it is relevant, can you maybe share an example?

Again, a platform only defines version constraints for things you declare without version. It does not add any dependency, so there is nothing to exclude. If you want to exclude a transitive dependency, exclude it where it is included.

A platform may define constrains by depending on another platform or on a Maven bom. If the constraints in that transitive platform or bom are unwanted, excluding it helps.

As far as I can tell, this doesn’t work as you would expect due to a bug in the Kotlin DSL. The DSL seems to think the receiver should be a Configuration when it’s actually an ExternalModuleDependency. You can work around that with a cast:

dependencies {
    implementation(platform("com.alibaba.csp:sentinel-parameter-flow-control")) {
        (this as ExternalModuleDependency).exclude("com.alibaba.middleware", "metrics-integration")
    }
}

Note that this particular exclude may have no effect if metrics-integration is a constraint rather than a transitive platform or bom dependency. When importing a bom, allow a bom that it imports to be excluded · Issue #317 · spring-gradle-plugins/dependency-management-plugin · GitHub discusses a problem where such an exclude is useful and effective.

1 Like

Ah, thanks @Andy_Wilkinson, excluding an included bom from the bom indeed makes sense.

Btw., it does not think it is a Configuration.
The error says, that on Configuration there would be an exclude method with matching signature, but that it indeed is not in the context of a Configuration or it would have called it on that.

The Context is Dependency as platform(...) can work on all kinds of Dependency subclass and just cannot know which it works on. It just modifies its attributes, so input-type = output-type, which is why you can cast it to ExternalModuleDependency to make it work.

But having a closer look, I think the problem here indeed is the actual usage of platform(...).
The coordinates com.alibaba.csp:sentinel-parameter-flow-control do not provide a platform or BOM, but just a normal dependency.
So indeed the right solution here would most probably be to simply remove platform(...).

Sorry I misunderstand the meaning of platform.


I want to add dependency from parent or other module, without version. And add exclusion.

I tried platform, but I misunderstand it.


Here is the solution I figured out.

  1. introduce dependencyManagement module, add constraints.

    val sentinelVersion = "1.8.6"
    
    dependencies {
        constraints {
            api("com.alibaba.csp:sentinel-spring-webmvc-adapter:$sentinelVersion")
            api("com.alibaba.csp:sentinel-core:$sentinelVersion")
        }
    }
    
  2. add dependency in app module, with exclusion, without version.

    dependencies {
        implementation(enforcedPlatform(project(":dependencyManagement")))
        implementation("com.alibaba.csp:sentinel-spring-webmvc-adapter") {
            exclude("com.alibaba.csp", "sentinel-core")
        }
    }
    
  3. verify

    $ ./gradlew -q :app:dependencies
    
    ------------------------------------------------------------
    Project ':app'
    ------------------------------------------------------------
    
    runtimeClasspath - Runtime classpath of source set 'main'.
    +--- project :dependencyManagement
    |    \--- com.alibaba.csp:sentinel-spring-webmvc-adapter:1.8.6 (c)
    \--- com.alibaba.csp:sentinel-spring-webmvc-adapter -> 1.8.6
    $ ./gradlew -q run
    Hello, world!
    load adapter success!   com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.UrlCleaner
    load core failed!       java.lang.ClassNotFoundException: com.alibaba.csp.sentinel.Env
    

https://github.com/robberphex/gradle-example/blob/main/README.md

Still, thanks a lot to @Vampire @Andy_Wilkinson , thanks to your patience!

Actually, for defining versions centrally, I’d instead recommend to use a version catalog.
A platform is more helpful to control the versions of transitive dependencies.
But you can also combine a platform and a version catalog.

For your dependencyManagement project you should probably use the java-platform plugin.

And strongly consider not using enforcedPlatform, but platform. The latter should be the usually used one. The former is a very heavy hammer that should only be used in edge cases.