[GRADLE-2594] resolution of project dependency at configuration time does not evaluate project Created: 11/Dec/12  Updated: 11/Mar/13  Resolved: 11/Mar/13

Status: Resolved
Project: Gradle
Affects Version/s: 1.3
Fix Version/s: 1.5-rc-1

Type: Bug
Reporter: Howard M. Lewis Ship Assignee: Szczepan Faber
Resolution: Fixed Votes: 0


 Description   

I'm putting together some code that acts kind of like an application server.

I have a multi-project that defines:

  • a common runtime module (smash-runtime)
  • the main server module (smash-server)
  • a couple of example applications
  • the launcher module that puts everything together

The launcher copies the other projects dependencies to a particular file structure.

Mostly this is working great:

$ gr clean assembly ; tree build/server/
:smash-launcher:clean
:smash-runtime:compileJava UP-TO-DATE
:smash-runtime:processResources UP-TO-DATE
:smash-runtime:classes UP-TO-DATE
:smash-runtime:jar UP-TO-DATE
:netty-echo:compileJava UP-TO-DATE
:netty-echo:processResources UP-TO-DATE
:netty-echo:classes UP-TO-DATE
:netty-echo:jar UP-TO-DATE
:smash-launcher:compileJava
:smash-launcher:processResources UP-TO-DATE
:smash-launcher:classes
:smash-launcher:jar
:smash-server:compileJava UP-TO-DATE
:smash-server:processResources UP-TO-DATE
:smash-server:classes UP-TO-DATE
:smash-server:jar UP-TO-DATE
:web-client:compileJava UP-TO-DATE
:web-client:processResources UP-TO-DATE
:web-client:classes UP-TO-DATE
:web-client:jar UP-TO-DATE
:smash-launcher:assembly

BUILD SUCCESSFUL

Total time: 2.402 secs
build/server/
├── apps
│ ├── echo
│ │ ├── netty-3.5.11.Final.jar
│ │ └── netty-echo.jar
│ └── web
│ ├── antlr-2.7.7.jar
│ ├── antlr-runtime-3.3.jar
│ ├── commons-codec-1.5.jar
│ ├── javassist-3.12.1.GA.jar
│ ├── javax.inject-1.jar
│ ├── javax.servlet-3.0.0.v201112011016.jar
│ ├── jetty-continuation-8.1.8.v20121106.jar
│ ├── jetty-http-8.1.8.v20121106.jar
│ ├── jetty-io-8.1.8.v20121106.jar
│ ├── jetty-security-8.1.8.v20121106.jar
│ ├── jetty-server-8.1.8.v20121106.jar
│ ├── jetty-servlet-8.1.8.v20121106.jar
│ ├── jetty-util-8.1.8.v20121106.jar
│ ├── jetty-webapp-8.1.8.v20121106.jar
│ ├── jetty-xml-8.1.8.v20121106.jar
│ ├── log4j-1.2.16.jar
│ ├── plastic-5.3.6.jar
│ ├── slf4j-api-1.6.1.jar
│ ├── slf4j-log4j12-1.6.1.jar
│ ├── stringtemplate-3.2.1.jar
│ ├── tapestry-core-5.3.6.jar
│ ├── tapestry-func-5.3.6.jar
│ ├── tapestry-ioc-5.3.6.jar
│ ├── tapestry-json-5.3.6.jar
│ ├── tapestry5-annotations-5.3.6.jar
│ └── web-client.jar
├── boot
│ └── smash-server.jar
├── lib
│ └── smash-runtime.jar
└── smash-launcher.jar

5 directories, 31 files
~/workspaces/annadale/smash-prototype/smash-launcher
$

That's exactly the structure I want; apps/echo contains netty-echo.jar (my application) and its dependencies, apps/web contains web-client.jar and its dependencies.

smash-launcher/build.gradle is wonderfully concise:

description = "Bundle and launch a SMASH server."

configurations

{ boot echo web }

dependencies

{ provided project(":smash-runtime") boot project(":smash-server") echo project(":netty-echo") web project(":web-client") }

// Creates the Manifest Class-Path for provided dependencies, such as smash-runtime.
// Provided dependencies are needed by boot ("smash-server"), but are also available
// to applications.
def manifestClassPath() {
configurations.provided.files.collect { file -> "lib/${file.name}" }.join(" ")
}

jar {
manifest

{ attributes "Main-Class": "com.annadaletech.smash.SmashLauncher" attributes "Class-Path": manifestClassPath() }

}

task assembly(type: Copy) {
into "${project.buildDir}/server"
from jar

into("lib")

{ from configurations.provided }

into("boot")

{ from configurations.boot }

into("apps") {
into("echo")

{ from configurations.echo }

into("web")

{ from configurations.web }

}
}

My only issue is that when I've changed smash-runtime to have compile dependencies, those dependencies are NOT copied into the lib folder.

smash-runtime/build.gradle:

description = "Simple Minimal Application System Host - Runtime"

dependencies {
compile "org.slf4j:slf4j-api:${versions.slf4j}"
compile "log4j:log4j:1.2.17"
compile "org.slf4j:slf4j-log4j12:${versions.slf4j}"
}

I'm expecting to see the log4j.jar and friends in server/lib, but it is not present.

I get odd results using gradle dependencies:

$ gr dep
:smash-runtime:dependencies

------------------------------------------------------------
Project :smash-runtime - Simple Minimal Application System Host - Runtime
------------------------------------------------------------

archives - Configuration for archive artifacts.
No dependencies

compile - Classpath for compiling the main sources.
+--- org.slf4j:slf4j-api:1.7.2
+--- log4j:log4j:1.2.17
--- org.slf4j:slf4j-log4j12:1.7.2
+--- org.slf4j:slf4j-api:1.7.2
--- log4j:log4j:1.2.17

default - Configuration for default artifacts.
+--- org.slf4j:slf4j-api:1.7.2
+--- log4j:log4j:1.2.17
--- org.slf4j:slf4j-log4j12:1.7.2
+--- org.slf4j:slf4j-api:1.7.2
--- log4j:log4j:1.2.17

provided
No dependencies

runtime - Classpath for running the compiled main classes.
+--- org.slf4j:slf4j-api:1.7.2
+--- log4j:log4j:1.2.17
--- org.slf4j:slf4j-log4j12:1.7.2
+--- org.slf4j:slf4j-api:1.7.2
--- log4j:log4j:1.2.17

testCompile - Classpath for compiling the test sources.
+--- org.slf4j:slf4j-api:1.7.2
+--- log4j:log4j:1.2.17
--- org.slf4j:slf4j-log4j12:1.7.2
+--- org.slf4j:slf4j-api:1.7.2
--- log4j:log4j:1.2.17

testRuntime - Classpath for running the compiled test classes.
+--- org.slf4j:slf4j-api:1.7.2
+--- log4j:log4j:1.2.17
--- org.slf4j:slf4j-log4j12:1.7.2
+--- org.slf4j:slf4j-api:1.7.2
--- log4j:log4j:1.2.17

- dependencies omitted (listed previously)

BUILD SUCCESSFUL

Total time: 1.254 secs
~/workspaces/annadale/smash-prototype/smash-runtime
$

That's correct: you can see that the project smash-runtime has dependencies on SLF4j, LOG4j, etc.

However, in the neighboring smash-launcher:

$ gr dep
:smash-launcher:dependencies

------------------------------------------------------------
Project :smash-launcher - Bundle and launch a SMASH server.
------------------------------------------------------------

archives - Configuration for archive artifacts.
No dependencies

boot
--- smash-prototype:smash-server:unspecified

compile - Classpath for compiling the main sources.
No dependencies

default - Configuration for default artifacts.
No dependencies

echo
--- smash-prototype:netty-echo:unspecified
--- io.netty:netty:3.5.11.Final

provided
--- smash-prototype:smash-runtime:unspecified

runtime - Classpath for running the compiled main classes.
No dependencies

testCompile - Classpath for compiling the test sources.
No dependencies

testRuntime - Classpath for running the compiled test classes.
No dependencies

web
--- smash-prototype:web-client:unspecified
+--- org.apache.tapestry:tapestry-core:5.3.6

+--- org.apache.tapestry:tapestry-json:5.3.6
+--- org.antlr:antlr-runtime:3.3
  --- org.antlr:stringtemplate:3.2.1
  --- antlr:antlr:2.7.7
+--- org.apache.tapestry:tapestry-ioc:5.3.6
  +--- org.apache.tapestry:tapestry5-annotations:5.3.6
  +--- org.slf4j:slf4j-api:1.6.1
  +--- org.apache.tapestry:tapestry-func:5.3.6
  +--- org.slf4j:slf4j-log4j12:1.6.1
    +--- org.slf4j:slf4j-api:1.6.1
    --- log4j:log4j:1.2.16
  +--- javax.inject:javax.inject:1
  +--- org.apache.tapestry:plastic:5.3.6
  +--- log4j:log4j:1.2.14 -> 1.2.16
  --- javassist:javassist:3.12.1.GA
--- commons-codec:commons-codec:1.5
--- org.eclipse.jetty:jetty-webapp:8.1.8.v20121106
+--- org.eclipse.jetty:jetty-xml:8.1.8.v20121106
--- org.eclipse.jetty:jetty-util:8.1.8.v20121106
--- org.eclipse.jetty:jetty-servlet:8.1.8.v20121106
--- org.eclipse.jetty:jetty-security:8.1.8.v20121106
--- org.eclipse.jetty:jetty-server:8.1.8.v20121106
+--- org.eclipse.jetty.orbit:javax.servlet:3.0.0.v201112011016
+--- org.eclipse.jetty:jetty-continuation:8.1.8.v20121106
--- org.eclipse.jetty:jetty-http:8.1.8.v20121106
--- org.eclipse.jetty:jetty-io:8.1.8.v20121106
--- org.eclipse.jetty:jetty-util:8.1.8.v20121106

- dependencies omitted (listed previously)

BUILD SUCCESSFUL

Total time: 1.368 secs
~/workspaces/annadale/smash-prototype/smash-launcher
$

I'm not seeing the transitive dependencies of smash-runtime, just the output jar. I really don't get it, because there's no real difference between smash-runtime and web-client, but for web-client I am getting the transitive dependencies.

My work around is create a new configuration, "hackRuntime", that extends from provided, and recapitulates the logging dependencies. That works, but I'm trying to figure out if there's a bug, or if I'm doing something wrong.



 Comments   
Comment by Howard M. Lewis Ship [ 11/Dec/12 ]

Sorry the formatting for that came out so bizarre.

$ gr clean assembly ; tree build/server/
:smash-launcher:clean
:smash-runtime:compileJava UP-TO-DATE
:smash-runtime:processResources UP-TO-DATE
:smash-runtime:classes UP-TO-DATE
:smash-runtime:jar UP-TO-DATE
:netty-echo:compileJava UP-TO-DATE
:netty-echo:processResources UP-TO-DATE
:netty-echo:classes UP-TO-DATE
:netty-echo:jar UP-TO-DATE
:smash-launcher:compileJava
:smash-launcher:processResources UP-TO-DATE
:smash-launcher:classes
:smash-launcher:jar
:smash-server:compileJava UP-TO-DATE
:smash-server:processResources UP-TO-DATE
:smash-server:classes UP-TO-DATE
:smash-server:jar UP-TO-DATE
:web-client:compileJava UP-TO-DATE
:web-client:processResources UP-TO-DATE
:web-client:classes UP-TO-DATE
:web-client:jar UP-TO-DATE
:smash-launcher:assembly

BUILD SUCCESSFUL

Total time: 2.402 secs
build/server/
├── apps
│   ├── echo
│   │   ├── netty-3.5.11.Final.jar
│   │   └── netty-echo.jar
│   └── web
│       ├── antlr-2.7.7.jar
│       ├── antlr-runtime-3.3.jar
│       ├── commons-codec-1.5.jar
│       ├── javassist-3.12.1.GA.jar
│       ├── javax.inject-1.jar
│       ├── javax.servlet-3.0.0.v201112011016.jar
│       ├── jetty-continuation-8.1.8.v20121106.jar
│       ├── jetty-http-8.1.8.v20121106.jar
│       ├── jetty-io-8.1.8.v20121106.jar
│       ├── jetty-security-8.1.8.v20121106.jar
│       ├── jetty-server-8.1.8.v20121106.jar
│       ├── jetty-servlet-8.1.8.v20121106.jar
│       ├── jetty-util-8.1.8.v20121106.jar
│       ├── jetty-webapp-8.1.8.v20121106.jar
│       ├── jetty-xml-8.1.8.v20121106.jar
│       ├── log4j-1.2.16.jar
│       ├── plastic-5.3.6.jar
│       ├── slf4j-api-1.6.1.jar
│       ├── slf4j-log4j12-1.6.1.jar
│       ├── stringtemplate-3.2.1.jar
│       ├── tapestry-core-5.3.6.jar
│       ├── tapestry-func-5.3.6.jar
│       ├── tapestry-ioc-5.3.6.jar
│       ├── tapestry-json-5.3.6.jar
│       ├── tapestry5-annotations-5.3.6.jar
│       └── web-client.jar
├── boot
│   └── smash-server.jar
├── lib
│   └── smash-runtime.jar
└── smash-launcher.jar

5 directories, 31 files
~/workspaces/annadale/smash-prototype/smash-launcher
$


....

description = "Bundle and launch a SMASH server."

configurations {
    boot

    echo
    web
}

dependencies {
    provided project(":smash-runtime")

    boot project(":smash-server")

    echo project(":netty-echo")
    web project(":web-client")
}

// Creates the Manifest Class-Path for provided dependencies, such as smash-runtime.
// Provided dependencies are needed by boot ("smash-server"), but are also available
// to applications.
def manifestClassPath() {
    configurations.provided.files.collect { file -> "lib/${file.name}" }.join(" ")
}


jar {
    manifest {
        attributes "Main-Class": "com.annadaletech.smash.SmashLauncher"
        attributes "Class-Path": manifestClassPath()
    }
}

task assembly(type: Copy) {
    into "${project.buildDir}/server"
    from jar

    into("lib") { from configurations.provided }

    into("boot") { from configurations.boot }

    into("apps") {
        into("echo") { from configurations.echo }
        into("web") { from configurations.web }
    }
}

....

smash-runtime/build.gradle:

description = "Simple Minimal Application System Host - Runtime"

dependencies {
    compile "org.slf4j:slf4j-api:${versions.slf4j}"
    compile "log4j:log4j:1.2.17"
    compile "org.slf4j:slf4j-log4j12:${versions.slf4j}"
}

$ gr dep
:smash-runtime:dependencies

------------------------------------------------------------
Project :smash-runtime - Simple Minimal Application System Host - Runtime
------------------------------------------------------------

archives - Configuration for archive artifacts.
No dependencies

compile - Classpath for compiling the main sources.
+--- org.slf4j:slf4j-api:1.7.2
+--- log4j:log4j:1.2.17
\--- org.slf4j:slf4j-log4j12:1.7.2
     +--- org.slf4j:slf4j-api:1.7.2 (*)
     \--- log4j:log4j:1.2.17 (*)

default - Configuration for default artifacts.
+--- org.slf4j:slf4j-api:1.7.2
+--- log4j:log4j:1.2.17
\--- org.slf4j:slf4j-log4j12:1.7.2
     +--- org.slf4j:slf4j-api:1.7.2 (*)
     \--- log4j:log4j:1.2.17 (*)

provided
No dependencies

runtime - Classpath for running the compiled main classes.
+--- org.slf4j:slf4j-api:1.7.2
+--- log4j:log4j:1.2.17
\--- org.slf4j:slf4j-log4j12:1.7.2
     +--- org.slf4j:slf4j-api:1.7.2 (*)
     \--- log4j:log4j:1.2.17 (*)

testCompile - Classpath for compiling the test sources.
+--- org.slf4j:slf4j-api:1.7.2
+--- log4j:log4j:1.2.17
\--- org.slf4j:slf4j-log4j12:1.7.2
     +--- org.slf4j:slf4j-api:1.7.2 (*)
     \--- log4j:log4j:1.2.17 (*)

testRuntime - Classpath for running the compiled test classes.
+--- org.slf4j:slf4j-api:1.7.2
+--- log4j:log4j:1.2.17
\--- org.slf4j:slf4j-log4j12:1.7.2
     +--- org.slf4j:slf4j-api:1.7.2 (*)
     \--- log4j:log4j:1.2.17 (*)

(*) - dependencies omitted (listed previously)

BUILD SUCCESSFUL

Total time: 1.254 secs
~/workspaces/annadale/smash-prototype/smash-runtime
$ 

That's correct: you can see that the project smash-runtime has dependencies on SLF4j, LOG4j, etc.

However, in the neighboring smash-launcher:

$ gr dep
:smash-launcher:dependencies

------------------------------------------------------------
Project :smash-launcher - Bundle and launch a SMASH server.
------------------------------------------------------------

archives - Configuration for archive artifacts.
No dependencies

boot
\--- smash-prototype:smash-server:unspecified

compile - Classpath for compiling the main sources.
No dependencies

default - Configuration for default artifacts.
No dependencies

echo
\--- smash-prototype:netty-echo:unspecified
     \--- io.netty:netty:3.5.11.Final

provided
\--- smash-prototype:smash-runtime:unspecified

runtime - Classpath for running the compiled main classes.
No dependencies

testCompile - Classpath for compiling the test sources.
No dependencies

testRuntime - Classpath for running the compiled test classes.
No dependencies

web
\--- smash-prototype:web-client:unspecified
     +--- org.apache.tapestry:tapestry-core:5.3.6
     |    +--- org.apache.tapestry:tapestry-json:5.3.6
     |    +--- org.antlr:antlr-runtime:3.3
     |    |    \--- org.antlr:stringtemplate:3.2.1
     |    |         \--- antlr:antlr:2.7.7
     |    +--- org.apache.tapestry:tapestry-ioc:5.3.6
     |    |    +--- org.apache.tapestry:tapestry5-annotations:5.3.6
     |    |    +--- org.slf4j:slf4j-api:1.6.1
     |    |    +--- org.apache.tapestry:tapestry-func:5.3.6
     |    |    +--- org.slf4j:slf4j-log4j12:1.6.1
     |    |    |    +--- org.slf4j:slf4j-api:1.6.1 (*)
     |    |    |    \--- log4j:log4j:1.2.16
     |    |    +--- javax.inject:javax.inject:1
     |    |    +--- org.apache.tapestry:plastic:5.3.6
     |    |    +--- log4j:log4j:1.2.14 -> 1.2.16 (*)
     |    |    \--- javassist:javassist:3.12.1.GA
     |    \--- commons-codec:commons-codec:1.5
     \--- org.eclipse.jetty:jetty-webapp:8.1.8.v20121106
          +--- org.eclipse.jetty:jetty-xml:8.1.8.v20121106
          |    \--- org.eclipse.jetty:jetty-util:8.1.8.v20121106
          \--- org.eclipse.jetty:jetty-servlet:8.1.8.v20121106
               \--- org.eclipse.jetty:jetty-security:8.1.8.v20121106
                    \--- org.eclipse.jetty:jetty-server:8.1.8.v20121106
                         +--- org.eclipse.jetty.orbit:javax.servlet:3.0.0.v201112011016
                         +--- org.eclipse.jetty:jetty-continuation:8.1.8.v20121106
                         \--- org.eclipse.jetty:jetty-http:8.1.8.v20121106
                              \--- org.eclipse.jetty:jetty-io:8.1.8.v20121106
                                   \--- org.eclipse.jetty:jetty-util:8.1.8.v20121106 (*)

(*) - dependencies omitted (listed previously)

BUILD SUCCESSFUL

Total time: 1.368 secs
~/workspaces/annadale/smash-prototype/smash-launcher
$ 

Comment by Peter Walker (Inactive) [ 15/Dec/12 ]

I suspect this "provided project(":smash-runtime")".
If you want to copy smash-runtime and all of its transitives, try "compile project(":smash-runtime")"

Comment by Szczepan Faber [ 12/Feb/13 ]

This is already fixed in the master and will be released with 1.5. Project dependencies resolved at configuration time now force the target project to get configured first. @Howard, I think the proper solution to the problem would be to make it lazy. For example, you could configure the jar task manifest in a doFirst action. This way, the resolution of the provided configuration would happen at execution time.

Hope that helps!

Generated at Wed Jun 30 12:26:10 CDT 2021 using Jira 8.4.2#804003-sha1:d21414fc212e3af190e92c2d2ac41299b89402cf.