Multiproject build and fat jar

I’m trying to make a build with root project, and one spring boot project and one project with react components for frontend.

I want to pack frontend components to jar, and then build fat jar for spring boot app with fontend jar in WEB-INF\lib\ in fat jar.

Fromtend jar built with id(“com.moowork.node”) gradle plugin, and produced jar:

val npm_run_build = tasks.getByName("npm_run_build") {

    if (this == null) throw Exception("npm_run_build is null")

    inputs.files(fileTree("public"))
    inputs.files(fileTree("src"))

    inputs.file("package.json")
    inputs.file("package-lock.json")

    outputs.dir("build")

    println("npm_run_build")
}

val packageNpmApp by tasks.registering(Zip::class) {
    dependsOn(npm_run_build)
    archiveBaseName.set("app-react-components")
    archiveExtension.set("jar")
    destinationDirectory.set(File("$projectDir/build_packageNpmApp"))
    from("build")
    into("static")
}

val npmResources by configurations.creating

configurations {
    // npmResources
    default.get().extendsFrom(npmResources)
}

artifacts {
    add("archives", packageNpmApp) {
        type = "jar"
        builtBy(packageNpmApp)
    }
}

This jar appears after build, all seems ok. Next, in spring boot application I add dependency to frontend project:

dependencies {
       ...
	runtimeOnly(project(":app-react-components"))
	// implementation(project(":app-react-components"))
        ....
}

My github repo.

But frontend jar not appears in fat jar. What wrong and how to fix it?

Try changing the archives configuration to default in the artifacts declaration, e.g.:

artifacts {
    add("default", packageNpmApp) {
        type = "jar"
        builtBy(packageNpmApp)
    }
}

You will end up with the jar file in the BOOT-INF/lib folder, which I am not sure is what you want. Can you serve static content from a jar within the fat jar? If not, you can get the resources into the BOOT-INF/classes folder with something like:

val staticResources by configurations.creating

dependencies {
    staticResources(project(":app-react-components"))
}

tasks.withType<ProcessResources> {
    dependsOn(staticResources)
	from(staticResources.map { zipTree(it) })
}

You will probably get a double nested static folder, and in this case there is also no need to zip the content first if all you do is unzip it later. But hopefully there are some thoughts here to get you further.

artifacts {
    add("default", packageNpmApp) {
        type = "jar"
        builtBy(packageNpmApp)
    }
}

This change is that what I looking for. I can serve static content from nested jar in fat jar, Spring automatically add it to classpath, and available for http request after configuring resource handlers like this:

@Configuration
class WebConfiguration : WebMvcConfigurer {
   ...
   override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
        super.addResourceHandlers(registry)

        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/")
    }
   ...
}

Thank you for solution!

Oh, I didn’t know you could do that. Sweet :slight_smile: