I need to pack a jar
(or a war
, format is irrelevant, please read further) with the structure of common war
(wab
) archive. Meaning that I need WEB-INF/classes/lib
folder filled with dep-cy jar
s (not flattened/shaded) and all common stuff like resources, etc.
So, the main difference with the very common NON-osgi war
would be a properly written manifest. The problem is that BND
processes on the Jar
task of Gradle
, and then war plugin messes everything.
Right now I have reached the solution but I am not satisfied with it. And overall I feel there should be a better way. There are mostly two strategies:
- NOT using a
war
plugin and rely onBND
rich capabilites. - USE
war
pluging but rearrange somehow the build, so it does it's thing but lets theBND
do its thing as well supposedly AFTER thewar
. (So, FIRST theWAR
theBND
is AFTER.)
A little input data. I believe the is a major SUPER_BUG in bnd since everything I said is supposed to work with just one directive -wablib
, however, the major issue with it is that it works somehow in a diffwrent way rather than -includeresource
for exemple. -wablib
gets the input some sort of full_path_to_resource, which is not available while project evaluation and resolution by gradle and overall, it COULD be just brilliant IF it could take just a jar_name.jar
as includeresource
does. But it's not! So, even after trying to pull a string with full paths to all dependencies it is never done as gradle's configuration is not allowed to be manually resolved
to get those paths.
On the other hand the second listed way works but it looks and feels like a crutch. Like it should not be that way. I mean manually constructing the Bundle-ClassPath
and Include-Resources
How to painlessly create WAR
s WAB
s with war
gradle
plugin preferrably and not flattened/shaded?
Snippet (UPDATED)
I managed to avoid explicitly constructing manifestClasspath by just adding ;lib:=true
so bnd does it's thing.
tasks.withType<Jar> {
manifest {
val manifestIncludeJars = configurations.
implementation.
incoming.
dependencies.
joinToString(",") {
"lib/${it.name}.jar=${it.name}-[0-9]*.jar;lib:=true"
}
attributes(mapOf(
SNAPSHOT to "\${tstamp}-SNAPSHOT",
"Automatic-Module-Name" to "${project.group}.\${replace;\${bsn};[-_];.}",
BUNDLE_VERSION to project.version,
INCLUDERESOURCE to manifestIncludeJars
))
}
}
UPDATE
Also I managed to get what I want by just using bnd without gradle 'war' plugin. But that's not what I want. This constructs the whole jar
/war
/wab
whatever you call it with exactely the same structure as gradle 'war' plugin plus the proper manifest, but I want to separate the the proper manifest creation from assembling the archive so no delegation from gradle to bnd of the build tool functions
# [ WEB(APP) / WAB / WAR ]
-wab: src/main/webapp
-includeresource: WEB-INF/classes=src/main/resources
# This does the magic since gradle and bnd share properties during build
deps: ${project.sourceSets.main.runtimeClasspath.files}
# remove the square bracket form the last dependency so it to be incuded in archive
lastDep: {substring;${last;${deps}};0;-1}
-wablib: ${format;%s,;${filter;${deps},${lastDep};.*\.jar$}}