Skip to content

Commit f3b4403

Browse files
committed
Support exclusion of optional dependencies in uber-jars
Update Maven plugin with `<includeOptional>` configuration property that can be used to toggle if optional dependencies are packages. For back-compatibility, in 3.5.x the default is `true`. Fixes gh-25403
1 parent 8d63043 commit f3b4403

File tree

10 files changed

+335
-0
lines changed

10 files changed

+335
-0
lines changed

spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,42 @@ void whenAnEntryIsExcludedItDoesNotAppearInTheRepackagedJar(MavenBuild mavenBuil
202202
});
203203
}
204204

205+
@TestTemplate
206+
void whenAnEntryIsOptionalByDefaultAppearsInTheRepackagedJar(MavenBuild mavenBuild) {
207+
mavenBuild.project("jar-optional-default").goals("install").execute((project) -> {
208+
File repackaged = new File(project, "target/jar-optional-default-0.0.1.BUILD-SNAPSHOT.jar");
209+
assertThat(jar(repackaged)).hasEntryWithNameStartingWith("BOOT-INF/classes/")
210+
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-context")
211+
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-core")
212+
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-jcl")
213+
.hasEntryWithNameStartingWith("BOOT-INF/lib/log4j-api-");
214+
});
215+
}
216+
217+
@TestTemplate
218+
void whenAnEntryIsOptionalAndOptionalsIncludedAppearsInTheRepackagedJar(MavenBuild mavenBuild) {
219+
mavenBuild.project("jar-optional-include").goals("install").execute((project) -> {
220+
File repackaged = new File(project, "target/jar-optional-include-0.0.1.BUILD-SNAPSHOT.jar");
221+
assertThat(jar(repackaged)).hasEntryWithNameStartingWith("BOOT-INF/classes/")
222+
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-context")
223+
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-core")
224+
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-jcl")
225+
.hasEntryWithNameStartingWith("BOOT-INF/lib/log4j-api-");
226+
});
227+
}
228+
229+
@TestTemplate
230+
void whenAnEntryIsOptionalAndOptionalsExcludedDoesNotAppearInTheRepackagedJar(MavenBuild mavenBuild) {
231+
mavenBuild.project("jar-optional-exclude").goals("install").execute((project) -> {
232+
File repackaged = new File(project, "target/jar-optional-exclude-0.0.1.BUILD-SNAPSHOT.jar");
233+
assertThat(jar(repackaged)).hasEntryWithNameStartingWith("BOOT-INF/classes/")
234+
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-context")
235+
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-core")
236+
.hasEntryWithNameStartingWith("BOOT-INF/lib/spring-jcl")
237+
.doesNotHaveEntryWithNameStartingWith("BOOT-INF/lib/log4j-api-");
238+
});
239+
}
240+
205241
@TestTemplate
206242
void whenAnEntryIsExcludedWithPropertyItDoesNotAppearInTheRepackagedJar(MavenBuild mavenBuild) {
207243
mavenBuild.project("jar")
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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>jar-optional-default</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>repackage</goal>
23+
</goals>
24+
</execution>
25+
</executions>
26+
</plugin>
27+
<plugin>
28+
<groupId>org.apache.maven.plugins</groupId>
29+
<artifactId>maven-jar-plugin</artifactId>
30+
<version>@maven-jar-plugin.version@</version>
31+
</plugin>
32+
</plugins>
33+
</build>
34+
<dependencies>
35+
<dependency>
36+
<groupId>org.springframework</groupId>
37+
<artifactId>spring-context</artifactId>
38+
<version>@spring-framework.version@</version>
39+
</dependency>
40+
<dependency>
41+
<groupId>org.apache.logging.log4j</groupId>
42+
<artifactId>log4j-api</artifactId>
43+
<version>@log4j2.version@</version>
44+
<optional>true</optional>
45+
</dependency>
46+
</dependencies>
47+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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+
public class SampleApplication {
20+
21+
public static void main(String[] args) {
22+
}
23+
24+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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>jar-optional-exclude</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>repackage</goal>
23+
</goals>
24+
<configuration>
25+
<includeOptional>false</includeOptional>
26+
</configuration>
27+
</execution>
28+
</executions>
29+
</plugin>
30+
<plugin>
31+
<groupId>org.apache.maven.plugins</groupId>
32+
<artifactId>maven-jar-plugin</artifactId>
33+
<version>@maven-jar-plugin.version@</version>
34+
</plugin>
35+
</plugins>
36+
</build>
37+
<dependencies>
38+
<dependency>
39+
<groupId>org.springframework</groupId>
40+
<artifactId>spring-context</artifactId>
41+
<version>@spring-framework.version@</version>
42+
</dependency>
43+
<dependency>
44+
<groupId>org.apache.logging.log4j</groupId>
45+
<artifactId>log4j-api</artifactId>
46+
<version>@log4j2.version@</version>
47+
<optional>true</optional>
48+
</dependency>
49+
</dependencies>
50+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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+
public class SampleApplication {
20+
21+
public static void main(String[] args) {
22+
}
23+
24+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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>jar-optional-include</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>repackage</goal>
23+
</goals>
24+
<configuration>
25+
<includeOptional>true</includeOptional>
26+
</configuration>
27+
</execution>
28+
</executions>
29+
</plugin>
30+
<plugin>
31+
<groupId>org.apache.maven.plugins</groupId>
32+
<artifactId>maven-jar-plugin</artifactId>
33+
<version>@maven-jar-plugin.version@</version>
34+
</plugin>
35+
</plugins>
36+
</build>
37+
<dependencies>
38+
<dependency>
39+
<groupId>org.springframework</groupId>
40+
<artifactId>spring-context</artifactId>
41+
<version>@spring-framework.version@</version>
42+
</dependency>
43+
<dependency>
44+
<groupId>org.apache.logging.log4j</groupId>
45+
<artifactId>log4j-api</artifactId>
46+
<version>@log4j2.version@</version>
47+
<optional>true</optional>
48+
</dependency>
49+
</dependencies>
50+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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+
public class SampleApplication {
20+
21+
public static void main(String[] args) {
22+
}
23+
24+
}

spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo
111111
@Parameter(defaultValue = "false")
112112
public boolean includeSystemScope;
113113

114+
/**
115+
* Include optional dependencies.
116+
* @since 3.5.7
117+
*/
118+
@Parameter(defaultValue = "true")
119+
public boolean includeOptional = true;
120+
114121
/**
115122
* Include JAR tools.
116123
* @since 3.3.0
@@ -228,6 +235,9 @@ private ArtifactsFilter[] getAdditionalFilters() {
228235
if (!this.includeSystemScope) {
229236
filters.add(new ScopeFilter(null, Artifact.SCOPE_SYSTEM));
230237
}
238+
if (!this.includeOptional) {
239+
filters.add(DependencyFilter.exclude(Artifact::isOptional));
240+
}
231241
return filters.toArray(new ArtifactsFilter[0]);
232242
}
233243

spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/DependencyFilter.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616

1717
package org.springframework.boot.maven;
1818

19+
import java.util.Collections;
1920
import java.util.HashSet;
2021
import java.util.List;
2122
import java.util.Set;
23+
import java.util.function.Predicate;
2224

2325
import org.apache.maven.artifact.Artifact;
2426
import org.apache.maven.shared.artifact.filter.collection.AbstractArtifactsFilter;
@@ -81,4 +83,22 @@ protected final List<? extends FilterableDependency> getFilters() {
8183
return this.filters;
8284
}
8385

86+
/**
87+
* Return a new {@link DependencyFilter} the excludes artifacts based on the given
88+
* predicate.
89+
* @param filter the predicate used to filter the artifacts.
90+
* @return a new {@link DependencyFilter} instance
91+
* @since 3.5.7
92+
*/
93+
public static DependencyFilter exclude(Predicate<Artifact> filter) {
94+
return new DependencyFilter(Collections.emptyList()) {
95+
96+
@Override
97+
protected boolean filter(Artifact artifact) {
98+
return filter.test(artifact);
99+
}
100+
101+
};
102+
}
103+
84104
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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.springframework.boot.maven;
18+
19+
import java.util.Set;
20+
21+
import org.apache.maven.artifact.Artifact;
22+
import org.apache.maven.artifact.DefaultArtifact;
23+
import org.apache.maven.artifact.handler.ArtifactHandler;
24+
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
25+
import org.apache.maven.artifact.versioning.VersionRange;
26+
import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
27+
import org.junit.jupiter.api.Test;
28+
29+
import static org.assertj.core.api.Assertions.assertThat;
30+
31+
/**
32+
* Tests for {@link DependencyFilter}.
33+
*
34+
* @author Phillip Webb
35+
*/
36+
class DependencyFilterTests {
37+
38+
@Test
39+
void excludeFiltersBasedOnPredicate() throws ArtifactFilterException {
40+
DependencyFilter filter = DependencyFilter.exclude(Artifact::isOptional);
41+
ArtifactHandler ah = new DefaultArtifactHandler();
42+
VersionRange v = VersionRange.createFromVersion("1.0.0");
43+
DefaultArtifact a1 = new DefaultArtifact("com.example", "a1", v, "compile", "jar", null, ah, false);
44+
DefaultArtifact a2 = new DefaultArtifact("com.example", "a2", v, "compile", "jar", null, ah, true);
45+
DefaultArtifact a3 = new DefaultArtifact("com.example", "a3", v, "compile", "jar", null, ah, false);
46+
Set<Artifact> filtered = filter.filter(Set.of(a1, a2, a3));
47+
assertThat(filtered).containsExactlyInAnyOrder(a1, a3);
48+
}
49+
50+
}

0 commit comments

Comments
 (0)