Problem merging to WAR files using the 'with' method

As a prove of concept, let’s assume I have a project (myproject) with two WAR sub-projects in it (projectBase and projectSpecific); the base one has no dependencies but the specific one needs to include some content from the base one.

The project structure looks like this:

myproject
    projectBase
        src
            main
                webapp
                    index.html
                    welcome.html
    projectSpecific
        src
            main
                webapp
                    specific-welcome.html
    build.gradle
    settings.gradle

When building the specific project, I would like to also include the “index.html” from the base (this is just a prove of concept, my real project is much more complicated than this).

Here is the build file I use for that:

subprojects {
    apply plugin: 'war'
    war {
        if (project.name == 'projectSpecific') {
            with project(':projectBase').war {
                include 'index.html'
            }
        }
    }
}

When I run “gradle assemble”, the resulting specific WAR contains “specific-welcome.html” and “index.html”, as expected. But the base WAR contains only “index.html”; it’s missing its “welcome.html” file.

I don’t understand this behavior. It’s as if the “with” call was also applied to the base project, but clearly, I have a pre-condition to apply it only to the specific project.

I can probably find other ways of achieving what I need to do, but I would like to understand what’s happening…

Thanks!

Looks like you are reconfiguring ‘project(’:projectBase’).war’, then passing the result to ‘with’.

I see, that certainly explains the behavior. Thanks!

Is there another syntax for the “with” call to include the base WAR file, without reconfiguring it as a side effect?

You wouldn’t use ‘with’ to include the contents of a war, but ‘from { zipTree(war) }’. To include only parts of the contents, you could use ‘from { zipTree(war).matching { include … } }’.

That’s exactly what I needed, thank you!

For future reference, here is the updated build script that makes the original prove of concept work correctly:

subprojects {
    apply plugin: 'war'
        war {
            if (project.name == 'projectSpecific') {
                from {
                     zipTree("${project(':projectBase').buildDir}/libs/projectBase.war").matching { include 'index.html' }
                 }
            }
    }
}

It would be a bit nicer to do:

subprojects {
    apply plugin: "war"
}
  project(":projectSpecific") {
    war {
        from { ... }
    }
}