Only bundle sub-project jars in WAR -not transitive depencies

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Only bundle sub-project jars in WAR -not transitive depencies

anschoewe
Hello,

I have a WAR project with several subproject that the WAR depends on.  When I generate the WAR, I would like for the sub-project JARs to be bundled inside the war.  However, all transitive and compile time dependencies should be copied to an external folder/zip.  For example, suppose I have the following:

/WebApplication
  /lib
/SubProjectA
  /lib
/SubProjectB
  /lib
/build.gradle
/settings.gradle

When I generate the WAR from the WebApplication, I would like the following files produced:

webApplication.WAR.  It would contain
/lib/subProjectA.jar
/lib/subProjectB.jar

.... and a separate zip file would contain all of the other dependencies (both compile-time and run-time for the WebApplication and each sub project). Like

otherJars.zip
  /junit-addons-1.4.jar
  /xmlunit-1.2.jar
  /someJar-1.0.jar

My build.gradle currently looks something like this:

subprojects {
    usePlugin('java')
    version = '1.0'
    sourceCompatibility = 1.6
    targetCompatiblity = 1.6
}

/*
add the ability for the WAR to find all of the repositories of it's sub-projects.  That way,
it can bundle all of the dependent runtime jars from the sub-projects
*/
allprojects {
        afterEvaluate { project ->
                project.configurations.each { config ->
                        config.getDependencies(ProjectDependency.class).each {dep ->
                                dep.dependencyProject.repositories.each {repos ->
                                        if (!project.repositories.all.contains(repos)) {
                                                        project.repositories.add(repos)
                                        }
                                }
                        }
                }
        }
}

project(":SubProjectA") {
        dependencies {
                compile name: 'junit-addons', version: '1.4'
                runtime group: 'xmlunit', name: 'xmlunit', version: '1.2'
        }
}

project(":SubProjectB") {
        dependencies {
                compile project(":SubProjectA")
                compile group: 'junit-addons', name: 'junit-addons', version: '1.4'
                runtime group: 'xmlunit', name: 'xmlunit', version: '1.2'
        }
}

project(":WebApplication") {
        usePlugin('war')
        dependencies {
                compile project(":SubProjectB")
                runtime name 'someJar', version: '1.0'
        }
}

-----------
I don't understand what task to intercept/override to perform this kind of filtering.  My real project has more subprojects and dependent JARs. That's why I programmatically find all dependent transitive jars 'afterEvaluate' is called.

Any ideas?

Andrew
Reply | Threaded
Open this post in threaded view
|

Re: Only bundle sub-project jars in WAR -not transitive depencies

Adam Murdoch-2


anschoewe wrote:
> Hello,
>
> I have a WAR project with several subproject that the WAR depends on.  When
> I generate the WAR, I would like for the sub-project JARs to be bundled
> inside the war.  However, all transitive and compile time dependencies
> should be copied to an external folder/zip.

I'm curious why you want to do this?

Here's something that should do what you want (this is untested, but
should give you some idea of how to solve the problem)

project(':Web Application') {
    task warLibs(type: Copy) {
        from { projectDependencies() }
        into "$buildDir/war/libs"
    }

    war {
        dependsOn warLibs
        additionalLibs(dir: "$buildDir/war/libs")
    }

    task otherJarsZip(type: Zip) {
        from { configurations.runtime.files - projectDependencies().files }
    }

    def projectDependencies() {
        configurations.compile.copy { it instanceof ProjectDependency
}.setTransitive(false)
    }

}


If we get round to revising the archive task API in 0.9, this will be a
bit simpler (you won't need the copy for example)

>   For example, suppose I have the
> following:
>
> /WebApplication
>   /lib
> /SubProjectA
>   /lib
> /SubProjectB
>   /lib
> /build.gradle
> /settings.gradle
>
> When I generate the WAR from the WebApplication, I would like the following
> files produced:
>
> webApplication.WAR.  It would contain
> /lib/subProjectA.jar
> /lib/subProjectB.jar
>
> .... and a separate zip file would contain all of the other dependencies
> (both compile-time and run-time for the WebApplication and each sub
> project). Like
>
> otherJars.zip
>   /junit-addons-1.4.jar
>   /xmlunit-1.2.jar
>   /someJar-1.0.jar
>
> My build.gradle currently looks something like this:
>
> subprojects {
>     usePlugin('java')
>     version = '1.0'
>     sourceCompatibility = 1.6
>     targetCompatiblity = 1.6
> }
>
> /*
> add the ability for the WAR to find all of the repositories of it's
> sub-projects.  That way,
> it can bundle all of the dependent runtime jars from the sub-projects
> */
> allprojects {
> afterEvaluate { project ->
> project.configurations.each { config ->
> config.getDependencies(ProjectDependency.class).each {dep ->
> dep.dependencyProject.repositories.each {repos ->
> if (!project.repositories.all.contains(repos)) {
> project.repositories.add(repos)
> }
> }
> }
> }
> }
> }
>
> project(":SubProjectA") {
> dependencies {
> compile name: 'junit-addons', version: '1.4'
> runtime group: 'xmlunit', name: 'xmlunit', version: '1.2'
> }
> }
>
> project(":SubProjectB") {
> dependencies {
>                 compile project(":SubProjectA")
> compile group: 'junit-addons', name: 'junit-addons', version: '1.4'
> runtime group: 'xmlunit', name: 'xmlunit', version: '1.2'
> }
> }
>
> project(":WebApplication") {
>         usePlugin('war')
> dependencies {
>                 compile project(":SubProjectB")
> runtime name 'someJar', version: '1.0'
> }
> }
>
> -----------
> I don't understand what task to intercept/override to perform this kind of
> filtering.  My real project has more subprojects and dependent JARs. That's
> why I programmatically find all dependent transitive jars 'afterEvaluate' is
> called.
>
> Any ideas?
>
> Andrew
>
>  

--
Adam Murdoch
Gradle Developer
http://www.gradle.org


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Only bundle sub-project jars in WAR -not transitive depencies

anschoewe
Thanks for your help.  That got me started in the right direction and I was able to figure it out.

We want to do this because this web app, when deployed, will share many of the common jars with other web apps running in the same instance of Tomcat -only a few are unique to this web app.  This way, we don't need to duplicate jars in the web server.

However, this then made me wonder how I can switch between this custom war bundling, and the generic war bundling where all the jars are thrown into one war.  Is there an easy way to change configurations based on the task passed in at the command line?  For instance, I would like execute 'gradle war' to do the generic bundle-all war.  Conversely, I would like to executue 'gradle splitWar' to run a custom task that will do the split jar mode as I have configured now.  I couldn't find a way to dynamically assign different configurations in my war's dependencies depending on the task executed.  Is this possible?  Somehow I feel it must be, but I'm approaching this the wrong way.

Thank you again for your help.  Gradle is proving itself to be the simplest and most powerful build tool I've used.

Andrew
Reply | Threaded
Open this post in threaded view
|

Re: Only bundle sub-project jars in WAR -not transitive depencies

Adam Murdoch-2


anschoewe wrote:
> Thanks for your help.  That got me started in the right direction and I was
> able to figure it out.
>
> We want to do this because this web app, when deployed, will share many of
> the common jars with other web apps running in the same instance of Tomcat
> -only a few are unique to this web app.  This way, we don't need to
> duplicate jars in the web server.
>
>  

Right. Now it makes sense.

> However, this then made me wonder how I can switch between this custom war
> bundling, and the generic war bundling where all the jars are thrown into
> one war.  Is there an easy way to change configurations based on the task
> passed in at the command line?  For instance, I would like execute 'gradle
> war' to do the generic bundle-all war.

This is the default, so you can leave the 'war' task as it is. Each
additional War task you add to a project is initially configured exactly
the same way as the 'war' task. You can then tweak the configuration to
suit. So, your build can have a number of different War tasks, each of
which produces a slightly different WAR. For example:

usePlugin 'war'

task splitWar(type: War) {
    // include only the project dependencies (from previous example)

    // might also change the destination dir, or the war name, eg
    // classifier = 'split' or customname = 'split.war'
}

You can run gradle war to produce the standard war file, and gradle
splitWar to produce the split war file.

--
Adam Murdoch
Gradle Developer
http://www.gradle.org


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Only bundle sub-project jars in WAR -not transitive depencies

anschoewe
usePlugin 'war'

task splitWar(type: War) {
    // include only the project dependencies (from previous example)

    // might also change the destination dir, or the war name, eg
    // classifier = 'split' or customname = 'split.war'
}

You can run gradle war to produce the standard war file, and gradle
splitWar to produce the split war file.
Aaah.  I didn't realize the war{} entry in a project using the War plugin was just a task named 'war' of type War.  Now I see that you can define another task of type War (just giving it a unique name).  Also crucial to my understanding is that each task can have it's own set of dependencies.  I thought dependencies were only defined at the project level -not at the task level. I'm working on a multi-project build file.

I have this working now.  My web application project has two tasks of type: War.  However, as usual, this has led to another question.  Both of these War tasks add the same fileSet and zipFileSet.  Instead of redefining each fileSet/zipFileSet in each task, is there a way to define a common fileSet, in either a separate method or at the project level?  This way, each War could just add the fileSet/ZipFileSet from the common method/project properties.

Andrew
Reply | Threaded
Open this post in threaded view
|

Re: Only bundle sub-project jars in WAR -not transitive depencies

hans_d
Administrator

On Oct 29, 2009, at 3:57 PM, anschoewe wrote:

<snip>

> I have this working now.  My web application project has two tasks  
> of type:
> War.  However, as usual, this has led to another question.  Both of  
> these
> War tasks add the same fileSet and zipFileSet.  Instead of  
> redefining each
> fileSet/zipFileSet in each task, is there a way to define a common  
> fileSet,
> in either a separate method or at the project level?  This way, each  
> War
> could just add the fileSet/ZipFileSet from the common method/project
> properties.

You could do some awkward stuff to make this work for 0.8.

In trunk we have a straight forward solution for that.

In which one would you be interested?

- Hans

--
Hans Dockter
Gradle Project Manager
http://www.gradle.org

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Only bundle sub-project jars in WAR -not transitive depencies

anschoewe

hdockter wrote
You could do some awkward stuff to make this work for 0.8.

In trunk we have a straight forward solution for that.

In which one would you be interested?
I'll take the 'trunk' solution please. Might as well do it right, assuming version 0.9 will be released soon.

Thanks,

Andrew
Reply | Threaded
Open this post in threaded view
|

Re: Only bundle sub-project jars in WAR -not transitive depencies

hans_d
Administrator

On Oct 31, 2009, at 3:36 PM, anschoewe wrote:

>
>
>
> hdockter wrote:
>>
>>
>> You could do some awkward stuff to make this work for 0.8.
>>
>> In trunk we have a straight forward solution for that.
>>
>> In which one would you be interested?
>>
>
> I'll take the 'trunk' solution please. Might as well do it right, assuming
> version 0.9 will be released soon.

It took a bit longer until everything has been implemented. The API for the archives has changed compared to 0.8. You can specify what is in an archive now in the same way as you specify what needs to be copied. We call this a copySpec. Either you specify it directly in the archive or, in your case, you can do:

mySpec = copySpec {
   from '...'
   into // in the context of an archive this is the same as the prefix of an ant zipfileset
}

task war1(type: War) {
   from mySpec
   from ....
}

task war2(type: War) {
   from mySpec
   from ....
}

- Hans

--
Hans Dockter
Gradle Project Manager
http://www.gradle.org

>
> Thanks,
>
> Andrew
> --
> View this message in context: http://old.nabble.com/Only-bundle-sub-project-jars-in-WAR--not-transitive-depencies-tp25965185p26142848.html
> Sent from the gradle-user mailing list archive at Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>    http://xircles.codehaus.org/manage_email
>
>


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email