In my project I have the front-end part in the same codebase. Consequently, I have a couple of calls to exec-maven-plugin to build the front-end. And as a very last step, I have build-image goal execution.

For some reason build-image triggers execution of the whole build cycle again:

...
[INFO] >>> spring-boot-maven-plugin:2.4.5:build-image (default) > package @ spring-boot-build-image-double-build >>>
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ spring-boot-build-image-double-build ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ spring-boot-build-image-double-build ---
[INFO] 
...

The following project can be used to reproduce the problem: https://github.com/alexey-anufriev/spring-boot-build-image-double-build

Comment From: snicoll

Thanks for the sample but it fails for me:

[ERROR] Command execution failed. java.io.IOException: Cannot run program "yarn" (in directory "/Users/snicoll/Downloads/spring-boot-build-image-double-build-master/src/main/resources/frontend"): error=2, No such file or directory

Comment From: alexey-anufriev

@snicoll, I am sorry, forgot to mention this, for the front-end compilation you need Yarn, here is how you can get it https://classic.yarnpkg.com/en/docs/install/#mac-stable

Comment From: scottfrederick

This is happening because the build-image goal forks the lifecycle to run the package phase. This was likely done to ensure that the jar or war file is built successfully before packaging it into an image. Running mvn clean spring-boot:build-image will result in the jar or war being built and then packaged into an image.

If we remove the lifecycle forking, running mvn clean package with build-image bound to the package phase will be more efficient because the package phase will only be run once instead of twice, but running mvn clean spring-boot:build-image will result in an error because the jar or war file will not exist when the build-image goal is run.

For comparison, the spring-boot:repackage goal does not fork the lifecycle and does not automatically run package to build the jar or war before trying to repackage it. Running mvn clean spring-boot:repackage results in the (somewhat cryptic) error message repackage failed: Source file must not be null.

Flagging this for team attention to discuss what, if anything, we want to do about this.

Comment From: alexey-anufriev

@scottfrederick, thank you for your feedback. Would it be possible to consider another maven goal, something like compose-image that will rely on artifacts presence?

Comment From: philwebb

We're going to investigate if we can add a no-fork option or variant.

Comment From: martijndebruijn

What is the current status of this issue? I'm using Spring Boot 2.6.2 and the compile steps are still executed twice. When will this be solved? Do we have a workaround?

Comment From: philwebb

@martijndebruijn The issue is in the 2.x milestone which means it's something we'd like to fix with Spring Boot 2, but we don't have a more specific milestone. We can't really say when it will be solved I'm afraid. We do tend to prioritize issues If they get a pull-request from the community.

Comment From: OLibutzki

In a Spring Boot 2.7.x application, I currently use 3.2.0 of the spring-boot-maven-plugin in order to use build-image-no-fork. At first glance it seems to work. Do you see any obvious problems that might occur?

Comment From: bclozel

@OLibutzki we don't, as we've never tested this combination. If a problem arises with this setup we won't be able to support you as this is mixing incompatible Spring Boot versions.