What

Make it possible to generate bootable layer structure suitable for building container images without having to first generate and extract bootJar.

Why

Currently in order to generate bootable directory structure we need to first generate bootJar and then run java -Djarmode=layertools -jar <...>.jar extract.

For container image build process we usually only need the directories, so generating JAR and extracting it are unnecessary additional steps.

Comment From: wilkinsona

Thanks for the suggestion. Have you considered adding a task to your build that extracts the layers from bootJar? It would look something like this:

tasks.register('layeredApp', JavaExec) {
    def outputDirectory = project.layout.buildDirectory.dir('layeredApp')
    outputs.dir(outputDirectory)
    classpath(tasks.named('bootJar'))
    systemProperty('jarmode', 'layertools')
    args('extract')
    workingDir(outputDirectory)
}

Running ./gradlew layeredApp will then result in build/layeredApp containing the extracted layer directories.

Comment From: nakamorichi

Hi. Thank you for suggestion. Currently I have this kind of task:

tasks.register("extractBootJar") {
    doLast {
        exec {
            workingDir("./build/libs")
            commandLine("java", "-Djarmode=layertools", "-jar", "app.jar", "extract")
        }
    }
}

However, both approaches still require the JAR. I took a look at the plugin code, and I guess the reason for creating the JAR is to be able to utilize the logic provided by Jar task? I wonder how difficult it would be to create the dir structure without Jar task?

Comment From: wilkinsona

However, both approaches still require the JAR

Why do you want to avoid that? Tasks that creates archives (zips, wars, jars, and so on) are deliberately not cacheable in a Gradle build as creating them each time is faster than the caching overhead.

I took a look at the plugin code, and I guess the reason for creating the JAR is to be able to utilize the logic provided by Jar task?

No, not really. Spring Boot aims for the jar (or war) to be the single source of all of the information that's needed as an input to further steps in a CI/CD pipeline. For example, in Spring Boot 3.0, buildpacks can create a native image from a Spring Boot jar. Similarly, they can create a layered container image from a Spring Boot jar as well.

While it would technically possible to move the layering logic out of the creation of the jar or war, I think it would be a step backwards overall. We'd either have to make a breaking change and no longer allow layers to be configured on an individual BootJar or BootWar task or we'd have to offer the same configuration capabilities in two places. Both of these are hard to justify if the only benefit is avoiding the creation of the jar.

Comment From: nakamorichi

@wilkinsona Generating JAR just seems like an unnecessary step considering layered container image build. It's not a major issue to have to generate it and then extract, but I just don't quite see the purpose.

Comment From: nakamorichi

To follow the naming convention, it would be nice to have e.g. bootDir task that would only create the layered bootable directory structure.

Comment From: wilkinsona

I just don't quite see the purpose

As I said above, it's so that we can provide a single artifact from which various other artifacts, including a layered container image, can then be built. If you're building that container image as part of the same build, the intermediate jar artifact doesn't provide any benefit, but it also has hardly any cost. If you're building the layered container image in a later step in a deployment pipeline, the jar containing all of the necessary information has considerable benefits.

it would be nice to have e.g. bootDir task that would only create the layered bootable directory structure

We can't do that without fundamentally changing how layering is configured. The configuration would have to move from the bootJar task to somewhere else. That would be a breaking change just to avoid building the jar. As such, I don't think it can be justified. Thanks anyway for the suggestion.