Gradle still tries to figure out version of dependency even if it's excluded


(Paweł Stawicki) #1

In my project I have dependency on org.jboss.seam.validation:seam-validation-api:3.1.0.Final. It has dependency on javax.enterprise:cdi-api, but without version, so gradle fails to resolve it. It shouldn’t be a big deal, I can exclude javax.enterprise:cdi-api.

The problem is, even if excluded, gradle still tries to figure out version number, and fails the whole build.

Error message:

Could not resolve all dependencies for configuration ‘:compile’.

Could not resolve org.jboss.seam.validation:seam-validation-api:3.1.0.Final.

Required by:

com.smspl.mc5:mc5-web-ui:1.0.0-SNAPSHOT

Could not parse POM /Users/amorfis/.m2/repository/org/jboss/seam/validation/seam-validation-api/3.1.0.Final/seam-validation-api-3.1.0.Final.pom

Unable to resolve version for dependency ‘javax.enterprise:cdi-api:jar’

Could not parse POM https://nexus.softwaremill.com/content/groups/smlcommon-repos/org/jboss/seam/validation/seam-validation-api/3.1.0.Final/seam-validation-api-3.1.0.Final.pom

Unable to resolve version for dependency ‘javax.enterprise:cdi-api:jar’


(Peter Niederwieser) #2

Please include all relevant parts of the build script (wrapped in HTML code tags) and the output of ‘gradle -v’.


(Paweł Stawicki) #3

The build script is quite simple. Relevant part:

dependencies {
    compile(group: 'org.jboss.seam.validation', name: 'seam-validation-api', version: '3.1.0.Final') {
        exclude(module: 'cdi-api')
    }
}

gradle -v:

------------------------------------------------------------
Gradle 1.10
------------------------------------------------------------
  Build time:
 2013-12-17 09:28:15 UTC
Build number: none
Revision:
   36ced393628875ff15575fa03d16c1349ffe8bb6
  Groovy:
     1.8.6
Ant:
        Apache Ant(TM) version 1.9.2 compiled on July 8 2013
Ivy:
        2.2.0
JVM:
        1.7.0_25 (Oracle Corporation 23.25-b01)
OS:
         Mac OS X 10.9.1 x86_64

I’m the author of this question on SO: http://stackoverflow.com/questions/20935891/gradle-cannot-resolve-dependency


(Benjamin Muschko) #4

Could you please also provide us with the repositories you are using?


(Paweł Stawicki) #5

Sure:

repositories {
    mavenLocal()
    maven { url "http://repository.jboss.org/" }
    maven { url "https://nexus.softwaremill.com/content/groups/smlcommon-repos/" }
    mavenCentral()
}

This specific archives are in jboss repo.


(Benjamin Muschko) #6

Thanks, I can reproduce the issue. The exclude of the module doesn’t work at the moment as the version of the dependency cannot be resolving when parsing the POM (which happens earlier than the exclude). I think we will need to be less strict in this case (especially because the scope of “cdi-api” is “provided”).


(Peter Niederwieser) #7

My first question would be whether this is a valid Maven POM, and if so, why.


(Benjamin Muschko) #8

I think it’s debatable. On the one hand the version cannot be resolved which means that the dependency would generally not be resolvable. On the other hand the POM at least is treated gracefully when resolving it through Maven. My guess is that Maven also has a look at the scope. If the scope is not “compile” or “runtime”, then it doesn’t care about the missing version.


(Peter Niederwieser) #9

According to http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html, ‘provided’ dependencies go on the same module’s test class path. If that’s true, they need a version. Are we sure that in the concrete case, the version isn’t hidden somewhere?


(Benjamin Muschko) #10

I found a defined version of that dependency deeply nested in imported POMs:

https://nexus.softwaremill.com/content/groups/smlcommon-repos/org/jboss/seam/validation/seam-validation-api/3.1.0.Final/seam-validation-api-3.1.0.Final.pom -> (POM parent) https://nexus.softwaremill.com/content/groups/smlcommon-repos/org/jboss/seam/validation/seam-validation-parent/3.1.0.Final/seam-validation-parent-3.1.0.Final.pom -> (POM import) https://nexus.softwaremill.com/content/groups/smlcommon-repos/org/jboss/seam/seam-bom/3.1.0.Final/seam-bom-3.1.0.Final.pom -> (POM import) https://nexus.softwaremill.com/content/groups/smlcommon-repos/org/jboss/spec/jboss-javaee-6.0/2.0.0.Final/jboss-javaee-6.0-2.0.0.Final.pom -> (POM import) https://nexus.softwaremill.com/content/groups/smlcommon-repos/org/jboss/spec/jboss-javaee6-specs-bom/2.0.0.Final/jboss-javaee6-specs-bom-2.0.0.Final.pom

Do you think that should work?


(Peter Niederwieser) #11

Good question, but it looks reasonable. (I wish there was a spec for this stuff.) Do we currently support ‘import’ for less fancy cases?


(Benjamin Muschko) #12

We do support the POM import scope. I guess we’d need to set up a more complex test case to see what is going wrong there.


(Paweł Stawicki) #13

Shouldn’t it first exclude, and then try to resolve version? Seems to make most sense for me.


(Benjamin Muschko) #14

I had a deeper look at this issue. In one of the POMs, seam-bom-3.1.0-Final.pom, that is part of the POM import chain, we see the following:

<dependencyManagement>
    <dependencies>
        <!--
import the individual Java EE 6 API spec versions
-->
        <dependency>
            <groupId>org.jboss.spec</groupId>
            <artifactId>jboss-javaee-6.0</artifactId>
            <version>${jboss.javaee.version}</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
        <!--
make Java EE 6 API available as stack artifact
-->
        <!--
yes, we really need this one too!
-->
        <dependency>
            <groupId>org.jboss.spec</groupId>
            <artifactId>jboss-javaee-6.0</artifactId>
            <version>${jboss.javaee.version}</version>
            <scope>provided</scope>
            <type>pom</type>
        </dependency>
        ...
    </dependencies>
</dependencyManagement>

The imported POM is declared with scope ‘import’, later is defined with scope ‘provided’. When we parse the POM and identify multiple dependencies with the same ‘groupId’, ‘artifactId’ and ‘version’ we pick the last. As the scope of the last definition is ‘provided’, we do not import the POM. That’s why the property and the relevant ‘dependencyManagement’ declaration cannot be resolved. I am not sure why the dependency was declared twice with different scopes.


(Benjamin Muschko) #15

I can see that rationale. It’s simply not how it works at the moment. That would certainly be a deeper change.


(Niklaus Bucher) #16

Concerning your last sentence I’ll try to explain:

The two imports have different meanings: The dependency-statement with scope ‘import’ imports all the definitions for the dependencies listed in the project/dependencyManagement/dependencies tag. The other one with scope ‘provided’ adds all the dependencies from the project/dependencies, like minimal/recommended dependencies. So you can define all the dependencies with the versions in dependencyManagement but you have not to add all in every case.

Hope it helps.


(Niklaus Bucher) #17

Btw. I’m looking forward to an implementation of this functionality in gradle. :slight_smile:


(Benjamin Muschko) #18

Would you mind trying this out with 1.12-rc-1?