On 07/12/2012, at 10:12 AM, Howard Lewis Ship wrote:

> 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(" ")

This method is going to resolve configurations.provided when the 
'smash-launcher' project's build script is executed, andthis script is executed 
before that of 'smash-server'. The result is a empty set of dependencies, 
because the dependencies for 'smash-server' have not been configured.

The workaround is to either:

1. Make the call to manifestClassPath() lazy.
2. Add evaluationDependsOn(":smash-server") to force 'smash-server' to be 
configured before resolving configurations.provided.

This is clearly not a very useful behaviour. There are 2 things we plan to do 
to make this work better:

* Configure a project on demand when a project dependency on it is resolved.
* Warn when you modify a configuration that has already been resolved as part 
of a project dependency (or an extendsFrom).


> }
> 
> 
> 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.
> 
> Thanks in advance,
> 
> Howard
> 
> 
> -- 
> Howard M. Lewis Ship
> 
> Creator of Apache Tapestry
> 
> The source for Tapestry training, mentoring and support. Contact me to learn 
> how I can get you up and productive in Tapestry fast!
> 
> (971) 678-5210
> http://howardlewisship.com


--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com

Reply via email to