diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AotGenerateMojo.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AotGenerateMojo.java index 6864f6668f..8b2f29755a 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AotGenerateMojo.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AotGenerateMojo.java @@ -45,7 +45,6 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.springframework.boot.loader.tools.RunProcess; -import org.springframework.util.FileSystemUtils; /** * Invoke the AOT engine on the application. @@ -83,7 +82,6 @@ public class AotGenerateMojo extends AbstractRunMojo { protected void run(File workingDirectory, String startClassName, Map environmentVariables) throws MojoExecutionException, MojoFailureException { try { - deletePreviousAotAssets(); generateAotAssets(workingDirectory, startClassName, environmentVariables); compileSourceFiles(getClassPathUrls()); copyNativeConfiguration(this.generatedResources.toPath()); @@ -93,12 +91,6 @@ public class AotGenerateMojo extends AbstractRunMojo { } } - private void deletePreviousAotAssets() { - FileSystemUtils.deleteRecursively(this.generatedSources); - FileSystemUtils.deleteRecursively(this.generatedResources); - FileSystemUtils.deleteRecursively(this.generatedClasses); - } - private void generateAotAssets(File workingDirectory, String startClassName, Map environmentVariables) throws MojoExecutionException { List args = new ArrayList<>(); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/AotProcessor.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/AotProcessor.java index 3d28dae824..ad8a3d4a8f 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/AotProcessor.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/AotProcessor.java @@ -38,6 +38,7 @@ import org.springframework.context.aot.ApplicationContextAotGenerator; import org.springframework.context.support.GenericApplicationContext; import org.springframework.javapoet.ClassName; import org.springframework.util.Assert; +import org.springframework.util.FileSystemUtils; /** * Entry point for AOT processing of a {@link SpringApplication}. @@ -95,6 +96,7 @@ public class AotProcessor { * Trigger the processing of the application managed by this instance. */ public void process() { + deleteExistingOutput(); AotProcessingHook hook = new AotProcessingHook(); SpringApplicationHooks.withHook(hook, this::callApplicationMainMethod); GenericApplicationContext applicationContext = hook.getApplicationContext(); @@ -103,6 +105,21 @@ public class AotProcessor { performAotProcessing(applicationContext); } + private void deleteExistingOutput() { + deleteExistingOutput(this.sourceOutput, this.resourceOutput, this.classOutput); + } + + private void deleteExistingOutput(Path... paths) { + for (Path path : paths) { + try { + FileSystemUtils.deleteRecursively(path); + } + catch (IOException ex) { + throw new RuntimeException("Failed to delete existing output in '" + path + "'"); + } + } + } + private void callApplicationMainMethod() { try { this.application.getMethod("main", String[].class).invoke(null, new Object[] { this.applicationArgs }); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/AotProcessorTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/AotProcessorTests.java index 4aeed4a84e..840cd6c582 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/AotProcessorTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/AotProcessorTests.java @@ -16,6 +16,8 @@ package org.springframework.boot; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.function.Consumer; @@ -76,6 +78,29 @@ class AotProcessorTests { .withMessageContaining("Usage:"); } + @Test + void processingDeletesExistingOutput(@TempDir Path directory) throws IOException { + Path sourceOutput = directory.resolve("source"); + Path resourceOutput = directory.resolve("resource"); + Path classOutput = directory.resolve("class"); + Path existingSourceOutput = createExisting(sourceOutput); + Path existingResourceOutput = createExisting(resourceOutput); + Path existingClassOutput = createExisting(classOutput); + AotProcessor processor = new AotProcessor(SampleApplication.class, new String[0], sourceOutput, resourceOutput, + classOutput, "com.example", "example"); + processor.process(); + assertThat(existingSourceOutput).doesNotExist(); + assertThat(existingResourceOutput).doesNotExist(); + assertThat(existingClassOutput).doesNotExist(); + } + + private Path createExisting(Path directory) throws IOException { + Path existing = directory.resolve("existing"); + Files.createDirectories(directory); + Files.createFile(existing); + return existing; + } + private Consumer hasGeneratedAssetsForSampleApplication() { return (directory) -> { assertThat(directory.resolve(