diff --git a/build-plugin/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/AotTests.java b/build-plugin/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/AotTests.java index a96ace27fc82..8fd4c68c252c 100644 --- a/build-plugin/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/AotTests.java +++ b/build-plugin/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/AotTests.java @@ -195,4 +195,39 @@ protected String buildLog(File project) { return contentOf(new File(project, "target/build.log")); } + @TestTemplate + void whenAotRunsWithDevtoolsInClasspathItIsExcluded(MavenBuild mavenBuild) { + mavenBuild.project("aot-exclude-devtools").goals("package").execute((project) -> { + // The test passes if the build completes successfully. + // If devtools were included, the AOT processing would fail because devtools + // uses features (like class proxies) that are not compatible with native + // images. + Path aotDirectory = project.toPath().resolve("target/spring-aot/main"); + assertThat(aotDirectory).exists(); + // Verify that source files were generated, indicating successful AOT + // processing + Path sourcesDirectory = aotDirectory.resolve("sources"); + assertThat(sourcesDirectory).exists(); + assertThat(collectRelativePaths(sourcesDirectory)).isNotEmpty(); + }); + } + + @TestTemplate + void whenTestAotRunsWithDevtoolsInClasspathItIsExcluded(MavenBuild mavenBuild) { + mavenBuild.project("aot-test-exclude-devtools").goals("process-test-classes").execute((project) -> { + // The test passes if the build completes successfully. + // If devtools were included, the test AOT processing would fail because + // devtools + // uses features (like class proxies) that are not compatible with native + // images. + Path aotDirectory = project.toPath().resolve("target/spring-aot/test"); + assertThat(aotDirectory).exists(); + // Verify that source files were generated, indicating successful AOT + // processing + Path sourcesDirectory = aotDirectory.resolve("sources"); + assertThat(sourcesDirectory).exists(); + assertThat(collectRelativePaths(sourcesDirectory)).isNotEmpty(); + }); + } + } diff --git a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-exclude-devtools/pom.xml b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-exclude-devtools/pom.xml new file mode 100644 index 000000000000..f8a155c6dadc --- /dev/null +++ b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-exclude-devtools/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + org.springframework.boot.maven.it + aot-exclude-devtools + 0.0.1.BUILD-SNAPSHOT + + UTF-8 + @java.version@ + @java.version@ + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + + process-aot + + + + + + + + + org.springframework.boot + spring-boot + @project.version@ + + + org.springframework.boot + spring-boot-devtools + @project.version@ + true + + + jakarta.servlet + jakarta.servlet-api + @jakarta-servlet.version@ + provided + + + \ No newline at end of file diff --git a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-exclude-devtools/src/main/java/org/test/SampleApplication.java b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-exclude-devtools/src/main/java/org/test/SampleApplication.java new file mode 100644 index 000000000000..6620ac4a2d82 --- /dev/null +++ b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-exclude-devtools/src/main/java/org/test/SampleApplication.java @@ -0,0 +1,29 @@ +/* + * Copyright 2012-present 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.test; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SampleApplication { + + public static void main(String[] args) { + SpringApplication.run(SampleApplication.class, args); + } + +} \ No newline at end of file diff --git a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-test-exclude-devtools/pom.xml b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-test-exclude-devtools/pom.xml new file mode 100644 index 000000000000..6db8ade0eac2 --- /dev/null +++ b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-test-exclude-devtools/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + org.springframework.boot.maven.it + aot-test-exclude-devtools + 0.0.1.BUILD-SNAPSHOT + + UTF-8 + @java.version@ + @java.version@ + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + + process-test-aot + + + + + + + + + org.springframework.boot + spring-boot + @project.version@ + + + org.springframework.boot + spring-boot-devtools + @project.version@ + true + + + org.springframework.boot + spring-boot-test + @project.version@ + test + + + org.junit.jupiter + junit-jupiter + @junit-jupiter.version@ + test + + + jakarta.servlet + jakarta.servlet-api + @jakarta-servlet.version@ + provided + + + \ No newline at end of file diff --git a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-test-exclude-devtools/src/main/java/org/test/SampleApplication.java b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-test-exclude-devtools/src/main/java/org/test/SampleApplication.java new file mode 100644 index 000000000000..6620ac4a2d82 --- /dev/null +++ b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-test-exclude-devtools/src/main/java/org/test/SampleApplication.java @@ -0,0 +1,29 @@ +/* + * Copyright 2012-present 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.test; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SampleApplication { + + public static void main(String[] args) { + SpringApplication.run(SampleApplication.class, args); + } + +} \ No newline at end of file diff --git a/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-test-exclude-devtools/src/test/java/org/test/SampleApplicationTests.java b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-test-exclude-devtools/src/test/java/org/test/SampleApplicationTests.java new file mode 100644 index 000000000000..cc23c3e14674 --- /dev/null +++ b/build-plugin/spring-boot-maven-plugin/src/intTest/projects/aot-test-exclude-devtools/src/test/java/org/test/SampleApplicationTests.java @@ -0,0 +1,29 @@ +/* + * Copyright 2012-present 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.test; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class SampleApplicationTests { + + @Test + void contextLoads() { + } + +} \ No newline at end of file diff --git a/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ProcessAotMojo.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ProcessAotMojo.java index c6c940e4e2b7..524594db73ed 100644 --- a/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ProcessAotMojo.java +++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ProcessAotMojo.java @@ -123,7 +123,7 @@ private String[] getAotArguments(String applicationClass) { private URL[] getClassPath() throws Exception { File[] directories = new File[] { this.classesDirectory, this.generatedClasses }; - return getClassPath(directories, new ExcludeTestScopeArtifactFilter()); + return getClassPath(directories, new ExcludeTestScopeArtifactFilter(), DEVTOOLS_EXCLUDE_FILTER); } private RunArguments resolveArguments() { diff --git a/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ProcessTestAotMojo.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ProcessTestAotMojo.java index 8cf523bdf114..6b3cf7929eb1 100644 --- a/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ProcessTestAotMojo.java +++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ProcessTestAotMojo.java @@ -148,7 +148,7 @@ private String[] getAotArguments() { protected URL[] getClassPath(boolean includeJUnitPlatformLauncher) throws Exception { File[] directories = new File[] { this.testClassesDirectory, this.generatedTestClasses, this.classesDirectory, this.generatedClasses }; - URL[] classPath = getClassPath(directories); + URL[] classPath = getClassPath(directories, DEVTOOLS_EXCLUDE_FILTER); if (!includeJUnitPlatformLauncher || this.project.getArtifactMap() .containsKey(JUNIT_PLATFORM_GROUP_ID + ":" + JUNIT_PLATFORM_LAUNCHER_ARTIFACT_ID)) { return classPath;