The problem: Given the following multi-project gradle
build
superproject
subproject-A -> war
subproject-B -> jar
I am looking for a way to configure subproject-B
to unpack the content of the war
generated by subproject-A
and have the content of the unpacked webapp
directory (with classes and resources for a deployment into a container) packed into the application distribution of subproject-B
at the root level along with the classes, resources and dependencies of the latter. So the structure of the distribution produced for subproject-B
should look like this:
subproject-B-0.1.0
bin/...
lib/
META-INF/ (<-- from B)
WEB-INF/ (<-- from A.war)
css/ (<-- from A.war)
js/ (<-- from A.war)
*.jar (code and dependencies of B)
The question of copying a resource from A to B was answered here. Here I need to copy the content of a dynamically generated build artifact (and generally it is ok if that is copied into main/resources
as the latter will be packed into the jar
).
The rationale: subproject-B
is a standalone Java app running tomcat-embed-server with a JavaFX WebView accessing the web app of subproject-B
on the localhost turning the otherwise web app into a sort of a standalone desktop app. It is 20 lines of code that run nicely in Eclipse, but seem to pose a packaging challenge for distribution.
I have finally found a solution so posting it here for the benefit of those facing a similar problem:
subprojectA/build.gradle
apply plugin: "java"
apply plugin: "war"
archivesBaseName = "subprojectA"
sourceCompatibility = 1.8
compileJava.options.encoding = "utf-8"
war {
manifest {
archiveName = "$baseName.$extension"
attributes "Implementation-Title": archivesBaseName,
"Implementation-Version": version
}
}
// declare configuration to refer to in superprojectB
configurations {
subprojectAwar
}
// make this configuration deliver the generated war
dependencies {
subprojectAwar files(war.archivePath)
}
subprojectB/build.gradle
apply plugin: "java"
apply plugin: 'application'
archivesBaseName = "subprojectB"
sourceCompatibility = 1.8
compileJava.options.encoding = "utf-8"
// declare configuration to take files from
configurations {
subprojectAwar
}
dependencies {
// bind the configuration to the respective configuration in subprojectA
subprojectAwar project(path: ":subprojectA", configuration: "subprojectAwar")
compile "org.apache.tomcat.embed:tomcat-embed-core:$tomcatEmbedVersion"
compile "org.apache.tomcat.embed:tomcat-embed-websocket:$tomcatEmbedVersion"
compile "org.apache.tomcat.embed:tomcat-embed-logging-log4j:$tomcatEmbedVersion"
compile "org.apache.tomcat.embed:tomcat-embed-jasper:$tomcatEmbedVersion"
}
mainClassName = 'org.project.subprojectB.StartServer'
jar {
// make sure this project is assembled after the war is generated
dependsOn(":subprojectA:assemble")
manifest {
archiveName = "$baseName.$extension"
attributes "Implementation-Title": archivesBaseName,
"Implementation-Version": version
attributes 'Main-Class': '$mainClassName'
}
// if you need to copy the content of the war into the jar:
// (otherwise only to the distribution, see below)
/*
from(zipTree(configurations.subprojectAwar.collect { it }[0])) {
into ""
exclude '**/META-INF/**'
}
*/
}
// copy the content of the war excluding META-INF into the lib of superprojectB
applicationDistribution.from(zipTree(configurations.subprojectAwar.collect { it }[0])) {
into "lib"
exclude '**/META-INF/**'
}