The eachFile() method in the War plugin ignores classpath


(Ryan Nelson) #1

In the War plugin, the eachFile() method does not iterate over files in the classpath (i.e., files in src/main/java and src/main/resources). I need to filter and rename some of the resource files as they are copied into the war. What’s the best way to handle this?

Example file structure:

/project/src/main/resources/resourceInClasspath.txt
/project/src/main/webapp/resourceInWebapp.txt

Example build script:

apply plugin: 'war'
  war {
 eachFile {
  println it
 }
}

Output:

C:\project>gradle clean war
:clean
:compileJava UP-TO-DATE
:processResources
:classes
:war
file 'C:\project\src\main\webapp\resourceInWebapp.txt'
  BUILD SUCCESSFUL
  Total time: 2.726 secs

(Luke Daley) #2

The copy task intentionally segregates the configuration of different sources/destinations.

war {

from(“somewhere”) {

eachFile {}

}

from(“somewhereElse”) {

eachFile {}

} }

Those two ‘from()’ segments are completely isolated from each other. The parent spec also has no visibility of children. This is intentional to allow copy specs to be safely composable.

However, there is a way to explicitly get visibility of everything:

war {
  rootSpec.eachFile {
    }
}

The ‘rootSpec’ is there for this purpose.


(Ryan Nelson) #3

Thanks, Luke, that helps immensely. I should mention, however, that the documentation is very unclear on this point. I can find no reference to a “rootSpec” in the DSL documentation or the User Guide. Google searches also produce mixed results.

In addition, the War DSL documentation should probably make clear that the eachFile(), exclude() and probably other methods only apply to the copy spec that copies the public files into the WAR.

I’m happy to take a crack at this, if you’d like. I’ve contributed a little documentation in the past.


(Luke Daley) #4

That would be very much appreciated.

This is not an aspect of WARs in particular though. This is relevant to any ‘Copy’ task (which is what the ‘war’ task is).


(Ryan Nelson) #5

Right, I understand that. I think perhaps this relationship should be more clear–it should be easy to see that there are actually two ‘from()’ segments, and that ‘eachFile()’ only applies to one of them. Otherwise the very name “eachFile” seems misleading. I’ll try to come up with something that explains this.

Also, just curious, rootSpec will allow me to access ALL files, but how to I access the ‘from()’ segment for the classpath inside the ‘War’ task? Is that even available to me in that task?


(Luke Daley) #6

Also, just curious, rootSpec will allow me to access ALL files, but how to I access the from() segment for the classpath inside the War task? Is that even available to me in that task?

AFAIK, there is no way to do this.