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