I'm using Spring Boot 2.3.3.

I've got a project where I'm building a fat JAR using the spring-boot-maven-plugin. I've configured the JAR to be executable and I've explicitly enabled layers. This is my configuration of the spring-boot-maven-plugin:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <executable>true</executable>
        <layers>
            <enabled>true</enabled>
        </layers>
    </configuration>
    <executions>
        <execution>
            <id>repackage</id>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

After building the project with mvn package, I try to extract the layers java -Djarmode=layertools -jar target/my-project-0.1.0-SNAPSHOT.jar extract --destination dest as described in this blog post on spring.io.

This gives me an empty directory for each of the layers:

$ ls -R dest
dest:
application  dependencies  snapshot-dependencies  spring-boot-loader

dest/application:

dest/dependencies:

dest/snapshot-dependencies:

dest/spring-boot-loader:

I would expect the directories to contain the class files of the different layers instead.

I noticed that this is caused by the JAR file being executable. I debugged through ExtractCommand.java and ZipInputStream#getNextEntry() will always return null for an executable JAR.

I think the options are to either improve the ExtractCommand (and possibly other commands) to work with executable JARs or to give a disclaimer in the documentation that the layertools don't work with executable JARs.

A fix could involve the following steps: * Call mark(2) on the FileInputStream to be able to later reset it in case the file is not executable. * Read the first two bytes from the FileInputStream and check if they match the "shebang" (#!) magic number (0x23 0x21). * In case the file doesn't start with a shebang, reset the input stream. * In case the file starts with a shebang, read bytes until the characters \necho 0 are read. * Wrap the input stream in a ZipInputStream and read the entries like before.

I know that this implementation won't be that easy, so I'd totally understand if you chose not to support executable JARs.

Comment From: scottfrederick

This is similar to #22223.

For Spring Boot 2.3.x, we should detect this condition in layertools and give a warning or error like we do for the bootBuildImage task.

For Spring Boot 2.4.x, we're hoping to be able to fix up the jar file properly in #22336.

Comment From: snicoll

I've switched this issue to documentation as keeping it as described made me think we've actually fixed that limitation.