From d351086a064fd8b12a32331d35708ba1f2b01a15 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 10 Oct 2022 22:02:25 +0100 Subject: [PATCH] Adapt to breaking changes to AOT processing entry points See gh-32550 --- .../context/SpringBootTestAotProcessor.java | 60 +++++++++++++++++++ .../boot/gradle/tasks/aot/ProcessTestAot.java | 2 +- .../spring-boot-maven-plugin/build.gradle | 1 + .../src/intTest/projects/aot-test/pom.xml | 6 ++ .../boot/maven/ProcessTestAotMojo.java | 2 +- .../boot/SpringApplicationAotProcessor.java | 31 +++------- .../SpringApplicationAotProcessorTests.java | 16 +++-- 7 files changed, 89 insertions(+), 29 deletions(-) create mode 100644 spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTestAotProcessor.java diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTestAotProcessor.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTestAotProcessor.java new file mode 100644 index 0000000000..a1b3b86d2f --- /dev/null +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTestAotProcessor.java @@ -0,0 +1,60 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.context; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.test.context.aot.TestAotProcessor; +import org.springframework.util.Assert; + +/** + * Entry point for AOT processing of a Spring Boot application's tests. + * + * For internal use only. + * + * @author Andy Wilkinson + * @since 3.0.0 + */ +public class SpringBootTestAotProcessor extends TestAotProcessor { + + /** + * Create a new processor for the specified test classpath roots and general settings. + * @param classpathRoots the classpath roots to scan for test classes + * @param settings the general AOT processor settings + */ + public SpringBootTestAotProcessor(Set classpathRoots, Settings settings) { + super(classpathRoots, settings); + } + + public static void main(String[] args) { + int requiredArgs = 6; + Assert.isTrue(args.length >= requiredArgs, + () -> "Usage: %s " + .formatted(TestAotProcessor.class.getName())); + Set classpathRoots = Arrays.stream(args[0].split(File.pathSeparator)).map(Paths::get) + .collect(Collectors.toSet()); + Settings settings = new Settings().setSourceOutput(Paths.get(args[1])).setResourceOutput(Paths.get(args[2])) + .setClassOutput(Paths.get(args[3])).setGroupId(args[4]).setArtifactId(args[5]); + new SpringBootTestAotProcessor(classpathRoots, settings).process(); + } + +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/aot/ProcessTestAot.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/aot/ProcessTestAot.java index e4ae58d611..0d73ca428c 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/aot/ProcessTestAot.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/aot/ProcessTestAot.java @@ -45,7 +45,7 @@ public class ProcessTestAot extends AbstractAot { private final Configuration junitPlatformLauncher; public ProcessTestAot() { - getMainClass().set("org.springframework.test.context.aot.TestAotProcessor"); + getMainClass().set("org.springframework.boot.test.context.SpringBootTestAotProcessor"); this.junitPlatformLauncher = createJUnitPlatformLauncher(); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle index 11885de237..8e9e81325e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle @@ -55,6 +55,7 @@ dependencies { } mavenRepository(project(path: ":spring-boot-project:spring-boot", configuration: "mavenRepository")) + mavenRepository(project(path: ":spring-boot-project:spring-boot-test", configuration: "mavenRepository")) runtimeOnly("org.sonatype.plexus:plexus-build-api") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/aot-test/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/aot-test/pom.xml index 3ceec06d98..88fb089d9f 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/aot-test/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/aot-test/pom.xml @@ -44,6 +44,12 @@ @spring-framework.version@ test + + org.springframework.boot + spring-boot-test + @project.version@ + test + org.assertj assertj-core diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ProcessTestAotMojo.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ProcessTestAotMojo.java index 63517dcb70..0d1a68d583 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ProcessTestAotMojo.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ProcessTestAotMojo.java @@ -58,7 +58,7 @@ public class ProcessTestAotMojo extends AbstractAotMojo { private static final String JUNIT_PLATFORM_LAUNCHER_ARTIFACT_ID = "junit-platform-launcher"; - private static final String AOT_PROCESSOR_CLASS_NAME = "org.springframework.test.context.aot.TestAotProcessor"; + private static final String AOT_PROCESSOR_CLASS_NAME = "org.springframework.boot.test.context.SpringBootTestAotProcessor"; /** * Directory containing the classes and resource files that should be packaged into diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationAotProcessor.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationAotProcessor.java index 8fea5e8a68..3dfd574bd5 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationAotProcessor.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationAotProcessor.java @@ -17,14 +17,13 @@ package org.springframework.boot; import java.lang.reflect.Method; -import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import org.springframework.boot.SpringApplication.AbandonedRunException; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.aot.AotProcessor; +import org.springframework.context.aot.ContextAotProcessor; import org.springframework.context.support.GenericApplicationContext; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; @@ -40,25 +39,18 @@ import org.springframework.util.function.ThrowingSupplier; * @author Phillip Webb * @since 3.0.0 */ -public class SpringApplicationAotProcessor extends AotProcessor { +public class SpringApplicationAotProcessor extends ContextAotProcessor { private final String[] applicationArgs; /** * Create a new processor for the specified application and settings. * @param application the application main class + * @param settings the general AOT processor settings * @param applicationArgs the arguments to provide to the main method - * @param sourceOutput the location of generated sources - * @param resourceOutput the location of generated resources - * @param classOutput the location of generated classes - * @param groupId the group ID of the application, used to locate - * native-image.properties - * @param artifactId the artifact ID of the application, used to locate - * native-image.properties */ - public SpringApplicationAotProcessor(Class application, String[] applicationArgs, Path sourceOutput, - Path resourceOutput, Path classOutput, String groupId, String artifactId) { - super(application, sourceOutput, resourceOutput, classOutput, groupId, artifactId); + public SpringApplicationAotProcessor(Class application, Settings settings, String[] applicationArgs) { + super(application, settings); this.applicationArgs = applicationArgs; } @@ -74,17 +66,12 @@ public class SpringApplicationAotProcessor extends AotProcessor { int requiredArgs = 6; Assert.isTrue(args.length >= requiredArgs, () -> "Usage: " + SpringApplicationAotProcessor.class.getName() + " "); - String applicationName = args[0]; - Path sourceOutput = Paths.get(args[1]); - Path resourceOutput = Paths.get(args[2]); - Path classOutput = Paths.get(args[3]); - String groupId = args[4]; - String artifactId = args[5]; + Class application = Class.forName(args[0]); + Settings settings = new Settings().setSourceOutput(Paths.get(args[1])).setResourceOutput(Paths.get(args[2])) + .setClassOutput(Paths.get(args[3])).setGroupId(args[4]).setArtifactId(args[5]); String[] applicationArgs = (args.length > requiredArgs) ? Arrays.copyOfRange(args, requiredArgs, args.length) : new String[0]; - Class application = Class.forName(applicationName); - new SpringApplicationAotProcessor(application, applicationArgs, sourceOutput, resourceOutput, classOutput, - groupId, artifactId).process(); + new SpringApplicationAotProcessor(application, settings, applicationArgs).process(); } /** diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationAotProcessorTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationAotProcessorTests.java index 047d8cc747..e98cc0b291 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationAotProcessorTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationAotProcessorTests.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.springframework.context.annotation.Configuration; +import org.springframework.context.aot.AbstractAotProcessor.Settings; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; @@ -45,9 +46,8 @@ class SpringApplicationAotProcessorTests { @Test void processApplicationInvokesRunMethod(@TempDir Path directory) { String[] arguments = new String[] { "1", "2" }; - SpringApplicationAotProcessor processor = new SpringApplicationAotProcessor(SampleApplication.class, arguments, - directory.resolve("source"), directory.resolve("resource"), directory.resolve("class"), "com.example", - "example"); + SpringApplicationAotProcessor processor = new SpringApplicationAotProcessor(SampleApplication.class, + settings(directory), arguments); processor.process(); assertThat(SampleApplication.argsHolder).isEqualTo(arguments); assertThat(SampleApplication.postRunInvoked).isFalse(); @@ -56,8 +56,7 @@ class SpringApplicationAotProcessorTests { @Test void processApplicationWithMainMethodThatDoesNotRun(@TempDir Path directory) { SpringApplicationAotProcessor processor = new SpringApplicationAotProcessor(BrokenApplication.class, - new String[0], directory.resolve("source"), directory.resolve("resource"), directory.resolve("class"), - "com.example", "example"); + settings(directory), new String[0]); assertThatIllegalStateException().isThrownBy(processor::process) .withMessageContaining("Does it run a SpringApplication?"); assertThat(directory).isEmptyDirectory(); @@ -80,6 +79,13 @@ class SpringApplicationAotProcessorTests { .withMessageContaining("Usage:"); } + private Settings settings(Path directory) { + return new Settings().setSourceOutput(directory.resolve("source")) + .setResourceOutput(directory.resolve("resource")).setClassOutput(directory.resolve("class")) + .setGroupId("com.example").setArtifactId("example"); + + } + @Configuration(proxyBeanMethods = false) public static class SampleApplication {