Why aren't my resources included in the uberjar I'm trying to build?


(Matt Stine) #1

I’m trying to build an uberjar based on the cookbook solution…that is working fine for classes and dependent jars. However, I can’t seem to get my resources (xml, etc.) included. Here’s the task defn:

task uberJar(type: Jar) {
  baseName = "foo-cacheserver-uberjar"
  from {
    sourceSets.main.output.classesDir
    sourceSets.main.output.resourcesDir
    configurations.compileNoGemFire.collect { it.isDirectory() ? it : zipTree(it) }
  }
}

FYI: compileNoGemFire is a special configuration that I’ve defined…and I am getting the expected results there.

Any ideas?

Thanks,

Matt Stine


(René Groeschke) #2

can you change the task to use the following syntax:

task uberJar(type: Jar) {
  baseName = "foo-cacheserver-uberjar"
  from sourceSets.main.output
  from configurations.compileNoGemFire.collect { it.isDirectory() ? it : zipTree(it) }
}

I think the syntax in your example above is not correct


(Matt Stine) #3

I previously had a similar syntax, but it did not work. The error is always:

You can’t change a configuration which is not in unresolved state!

In fact, the cookbook (http://docs.codehaus.org/display/GRADLE/Cookbook#Cookbook-Creatingafatjar), suggests the syntax that I used, and a JIRA indicates why (http://docs.codehaus.org/display/GRADLE/Cookbook#Cookbook-Creatingafatjar).

You did give a hint…I changed to:

task uberJar(type: Jar) {
  baseName = "foo-cacheserver-uberjar"
  from {
    sourceSets.main.output
    // configurations.compileNoGemFire.collect { it.isDirectory() ? it : zipTree(it) }
  }
}

If I do this…all of the classes and resources from the project make it. However, as soon as I uncomment the line dealing with the compileNoGemFire configuration, the project classes remain, but the resources do not. Strange.


(Matt Stine) #4

Another note of interest…

If I switch the order of the two lines inside the from closure, the dependencies are not included, but the project classes and resources ARE.


(René Groeschke) #5

the reason for that is that from { … } means that the closure is evaluated before passing it to the from closure. In a closure the last statement is interpreted as return value. That’s why you need at two seperate from blocks

It seems, that your resources are not part of the compileNoGemFire configuration but the classes are part of it.

A workaround might be putting just the from block with the configuration in a closure to defere the evaluation:

task uberJar(type: Jar) {
  baseName = "foo-cacheserver-uberjar"
  from sourceSets.main.output
  from { configurations.compileNoGemFire.collect { it.isDirectory() ? it : zipTree(it) } }
}

(Peter Niederwieser) #6

You need:

...
from sourceSets.main.output
from { configurations.compileNoGemFire.collect { it.isDirectory() ? it : zipTree(it) } }

‘collect’ realizes the configuration (thereby resolving it). To defer this until execution time, you need to wrap the expression in a closure.‘from { foo; bar; baz }’ (as in your original post) won’t work because ‘foo’ and ‘bar’ don’t contribute to the value returned from the closure. Apart from potential side effects, they are no-ops.


(Matt Stine) #7

Ahhhh…my slightly rusty Groovy-fu has gotten me into trouble. Totally forgot that only that last line of the closure is actually returned. (Had I been looking at a Clojure form, I would have totally spotted this!)

I suppose if I had somehow “accumulated” a collection of files and then returned that, it would have worked, no?

At any rate, your solution works perfectly guys. Thanks.


(Peter Niederwieser) #8

Concatenating with ‘+’ should have worked.


(Matt Stine) #9

Of course I could have saved myself some yak shaving and used: https://github.com/musketyr/gradle-fatjar-plugin

Solved my next problem, which was dealing w/ the Spring schema file concatenation…