Skip to content

Commit 99cf0e3

Browse files
academeysnicoll
authored andcommitted
Exclude spring-boot-devtools from AOT processing with Maven
Previously, spring-boot-devtools was only excluded from native images built with Gradle but not with Maven. This inconsistency meant that Maven builds would include devtools in the AOT processing classpath and in the native image, causing build failures. This commit harmonizes the situation and excludes devtools in a similar fashion with Maven. See gh-46533 Signed-off-by: academey <academey@gmail.com>
1 parent 6a55d7b commit 99cf0e3

File tree

9 files changed

+231
-2
lines changed

9 files changed

+231
-2
lines changed

build-plugin/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/AotTests.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,4 +195,26 @@ protected String buildLog(File project) {
195195
return contentOf(new File(project, "target/build.log"));
196196
}
197197

198+
@TestTemplate
199+
void whenAotRunsWithDevtoolsInClasspathItIsExcluded(MavenBuild mavenBuild) {
200+
mavenBuild.project("aot-exclude-devtools").goals("package").execute((project) -> {
201+
Path aotDirectory = project.toPath().resolve("target/spring-aot/main");
202+
assertThat(aotDirectory).exists();
203+
Path sourcesDirectory = aotDirectory.resolve("sources");
204+
assertThat(sourcesDirectory).exists();
205+
assertThat(collectRelativePaths(sourcesDirectory)).isNotEmpty();
206+
});
207+
}
208+
209+
@TestTemplate
210+
void whenTestAotRunsWithDevtoolsInClasspathItIsExcluded(MavenBuild mavenBuild) {
211+
mavenBuild.project("aot-test-exclude-devtools").goals("process-test-classes").execute((project) -> {
212+
Path aotDirectory = project.toPath().resolve("target/spring-aot/test");
213+
assertThat(aotDirectory).exists();
214+
Path sourcesDirectory = aotDirectory.resolve("sources");
215+
assertThat(sourcesDirectory).exists();
216+
assertThat(collectRelativePaths(sourcesDirectory)).isNotEmpty();
217+
});
218+
}
219+
198220
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<groupId>org.springframework.boot.maven.it</groupId>
6+
<artifactId>aot-exclude-devtools</artifactId>
7+
<version>0.0.1.BUILD-SNAPSHOT</version>
8+
<properties>
9+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
10+
<maven.compiler.source>@java.version@</maven.compiler.source>
11+
<maven.compiler.target>@java.version@</maven.compiler.target>
12+
</properties>
13+
<build>
14+
<plugins>
15+
<plugin>
16+
<groupId>@project.groupId@</groupId>
17+
<artifactId>@project.artifactId@</artifactId>
18+
<version>@project.version@</version>
19+
<executions>
20+
<execution>
21+
<goals>
22+
<goal>process-aot</goal>
23+
</goals>
24+
</execution>
25+
</executions>
26+
</plugin>
27+
</plugins>
28+
</build>
29+
<dependencies>
30+
<dependency>
31+
<groupId>org.springframework.boot</groupId>
32+
<artifactId>spring-boot</artifactId>
33+
<version>@project.version@</version>
34+
</dependency>
35+
<dependency>
36+
<groupId>org.springframework.boot</groupId>
37+
<artifactId>spring-boot-devtools</artifactId>
38+
<version>@project.version@</version>
39+
<optional>true</optional>
40+
</dependency>
41+
<dependency>
42+
<groupId>jakarta.servlet</groupId>
43+
<artifactId>jakarta.servlet-api</artifactId>
44+
<version>@jakarta-servlet.version@</version>
45+
<scope>provided</scope>
46+
</dependency>
47+
</dependencies>
48+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2012-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.test;
18+
19+
import org.springframework.boot.SpringApplication;
20+
import org.springframework.boot.autoconfigure.SpringBootApplication;
21+
22+
@SpringBootApplication
23+
public class SampleApplication {
24+
25+
public static void main(String[] args) {
26+
SpringApplication.run(SampleApplication.class, args);
27+
}
28+
29+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<groupId>org.springframework.boot.maven.it</groupId>
6+
<artifactId>aot-test-exclude-devtools</artifactId>
7+
<version>0.0.1.BUILD-SNAPSHOT</version>
8+
<properties>
9+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
10+
<maven.compiler.source>@java.version@</maven.compiler.source>
11+
<maven.compiler.target>@java.version@</maven.compiler.target>
12+
</properties>
13+
<build>
14+
<plugins>
15+
<plugin>
16+
<groupId>@project.groupId@</groupId>
17+
<artifactId>@project.artifactId@</artifactId>
18+
<version>@project.version@</version>
19+
<executions>
20+
<execution>
21+
<goals>
22+
<goal>process-test-aot</goal>
23+
</goals>
24+
</execution>
25+
</executions>
26+
</plugin>
27+
</plugins>
28+
</build>
29+
<dependencies>
30+
<dependency>
31+
<groupId>org.springframework.boot</groupId>
32+
<artifactId>spring-boot</artifactId>
33+
<version>@project.version@</version>
34+
</dependency>
35+
<dependency>
36+
<groupId>org.springframework.boot</groupId>
37+
<artifactId>spring-boot-devtools</artifactId>
38+
<version>@project.version@</version>
39+
<optional>true</optional>
40+
</dependency>
41+
<dependency>
42+
<groupId>org.springframework.boot</groupId>
43+
<artifactId>spring-boot-test</artifactId>
44+
<version>@project.version@</version>
45+
<scope>test</scope>
46+
</dependency>
47+
<dependency>
48+
<groupId>org.junit.jupiter</groupId>
49+
<artifactId>junit-jupiter</artifactId>
50+
<version>@junit-jupiter.version@</version>
51+
<scope>test</scope>
52+
</dependency>
53+
<dependency>
54+
<groupId>jakarta.servlet</groupId>
55+
<artifactId>jakarta.servlet-api</artifactId>
56+
<version>@jakarta-servlet.version@</version>
57+
<scope>provided</scope>
58+
</dependency>
59+
</dependencies>
60+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2012-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.test;
18+
19+
import org.springframework.boot.SpringApplication;
20+
import org.springframework.boot.autoconfigure.SpringBootApplication;
21+
22+
@SpringBootApplication
23+
public class SampleApplication {
24+
25+
public static void main(String[] args) {
26+
SpringApplication.run(SampleApplication.class, args);
27+
}
28+
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2012-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.test;
18+
19+
import org.junit.jupiter.api.Test;
20+
import org.springframework.boot.test.context.SpringBootTest;
21+
22+
@SpringBootTest
23+
class SampleApplicationTests {
24+
25+
@Test
26+
void contextLoads() {
27+
}
28+
29+
}

build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ProcessAotMojo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ private String[] getAotArguments(String applicationClass) {
130130

131131
private URL[] getClassPath() throws Exception {
132132
File[] directories = new File[] { this.classesDirectory, this.generatedClasses };
133-
return getClassPath(directories, new ExcludeTestScopeArtifactFilter());
133+
return getClassPath(directories, new ExcludeTestScopeArtifactFilter(), DEVTOOLS_EXCLUDE_FILTER);
134134
}
135135

136136
private RunArguments resolveArguments() {

build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ProcessTestAotMojo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ private String[] getAotArguments() {
154154
protected URL[] getClassPath(boolean includeJUnitPlatformLauncher) throws Exception {
155155
File[] directories = new File[] { this.testClassesDirectory, this.generatedTestClasses, this.classesDirectory,
156156
this.generatedClasses };
157-
URL[] classPath = getClassPath(directories);
157+
URL[] classPath = getClassPath(directories, DEVTOOLS_EXCLUDE_FILTER);
158158
if (!includeJUnitPlatformLauncher || this.project.getArtifactMap()
159159
.containsKey(JUNIT_PLATFORM_GROUP_ID + ":" + JUNIT_PLATFORM_LAUNCHER_ARTIFACT_ID)) {
160160
return classPath;

starter/spring-boot-starter-parent/build.gradle

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,12 @@ publishing.publications.withType(MavenPublication) {
298298
configuration {
299299
delegate.classesDirectory('${project.build.outputDirectory}')
300300
delegate.requiredVersion('22.3')
301+
exclusions {
302+
exclusion {
303+
delegate.groupId('org.springframework.boot')
304+
delegate.artifactId('spring-boot-devtools')
305+
}
306+
}
301307
}
302308
executions {
303309
execution {
@@ -342,6 +348,12 @@ publishing.publications.withType(MavenPublication) {
342348
configuration {
343349
delegate.classesDirectory('${project.build.outputDirectory}')
344350
delegate.requiredVersion('22.3')
351+
exclusions {
352+
exclusion {
353+
delegate.groupId('org.springframework.boot')
354+
delegate.artifactId('spring-boot-devtools')
355+
}
356+
}
345357
}
346358
executions {
347359
execution {

0 commit comments

Comments
 (0)