diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java index e964c2ecee7..05b6879901f 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java @@ -175,10 +175,25 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests { .hasEntryWithNameStartingWith("BOOT-INF/lib/spring-context") .hasEntryWithNameStartingWith("BOOT-INF/lib/spring-core") .hasEntryWithNameStartingWith("BOOT-INF/lib/spring-jcl") - .doesNotHaveEntryWithName("BOOT-INF/lib/servlet-api-2.5.jar"); + .doesNotHaveEntryWithNameStartingWith("BOOT-INF/lib/jakarta.servlet-api-"); }); } + @TestTemplate + void whenAnEntryIsExcludedWithPropertyItDoesNotAppearInTheRepackagedJar(MavenBuild mavenBuild) { + mavenBuild.project("jar") + .systemProperty("spring-boot.excludes", "jakarta.servlet:jakarta.servlet-api") + .goals("install") + .execute((project) -> { + File repackaged = new File(project, "target/jar-0.0.1.BUILD-SNAPSHOT.jar"); + assertThat(jar(repackaged)).hasEntryWithNameStartingWith("BOOT-INF/classes/") + .hasEntryWithNameStartingWith("BOOT-INF/lib/spring-context") + .hasEntryWithNameStartingWith("BOOT-INF/lib/spring-core") + .hasEntryWithNameStartingWith("BOOT-INF/lib/spring-jcl") + .doesNotHaveEntryWithNameStartingWith("BOOT-INF/lib/jakarta.servlet-api-"); + }); + } + @TestTemplate void whenAGroupIsExcludedNoEntriesInThatGroupAppearInTheRepackagedJar(MavenBuild mavenBuild) { mavenBuild.project("jar-exclude-group").goals("install").execute((project) -> { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractDependencyFilterMojo.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractDependencyFilterMojo.java index 0a665a04798..037b608a898 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractDependencyFilterMojo.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractDependencyFilterMojo.java @@ -82,7 +82,8 @@ public abstract class AbstractDependencyFilterMojo extends AbstractMojo { /** * Collection of artifact definitions to exclude. The {@link Exclude} element defines * mandatory {@code groupId} and {@code artifactId} properties and an optional - * {@code classifier} property. + * {@code classifier} property. If passing in excludes as a property the syntax is + *
-Dspring-boot.excludes=groupId1:artifactId1,groupId2:artifactId2:optional-qualifier* @since 1.1.0 */ @Parameter(property = "spring-boot.excludes") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Exclude.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Exclude.java index abacf74a351..9a795f11df5 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Exclude.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Exclude.java @@ -16,6 +16,8 @@ package org.springframework.boot.maven; +import org.springframework.util.Assert; + /** * A model for a dependency to exclude. * @@ -24,4 +26,17 @@ package org.springframework.boot.maven; */ public class Exclude extends FilterableDependency { + // Maven looks for this public method if giving excludes as property + // e.g. -Dspring-boot.excludes=myGroupId:myArtifactId:my-optional-classifier,foo:baz + public void set(String propertyInput) { + String[] parts = propertyInput.split(":"); + Assert.isTrue(parts.length == 2 || parts.length == 3, + "Exclude must be in the form groupId:artifactId:optional-classifier"); + setGroupId(parts[0]); + setArtifactId(parts[1]); + if (parts.length == 3) { + setClassifier(parts[2]); + } + } + }