diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/appendix-configuration-metadata.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/appendix-configuration-metadata.adoc
index 76abbc4361..f02eea3472 100644
--- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/appendix-configuration-metadata.adoc
+++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/appendix-configuration-metadata.adoc
@@ -713,30 +713,6 @@ With Maven the dependency should be declared as optional, as shown in the follow
----
-If you have defined `@ConfigurationProperties` in your application, make sure to configure the `spring-boot-maven-plugin` to prevent the `repackage` goal from adding the dependency into the fat jar:
-
-[source,xml,indent=0,subs="verbatim,quotes,attributes"]
-----
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
- org.springframework.boot
- spring-boot-configuration-processor
-
-
-
-
-
-
-
-----
-
With Gradle 4.5 and earlier, the dependency should be declared in the `compileOnly` configuration, as shown in the following example:
[source,groovy,indent=0,subs="verbatim,quotes,attributes"]
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 fb2a08c5c6..27252f7f8a 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
@@ -104,6 +104,7 @@ public abstract class AbstractDependencyFilterMojo extends AbstractMojo {
if (this.excludes != null && !this.excludes.isEmpty()) {
filters.addFilter(new ExcludeFilter(this.excludes));
}
+ filters.addFilter(new JarTypeFilter());
return filters;
}
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JarTypeFilter.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JarTypeFilter.java
new file mode 100644
index 0000000000..380be01ccd
--- /dev/null
+++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JarTypeFilter.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012-2020 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.maven;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.jar.JarFile;
+
+import org.apache.maven.artifact.Artifact;
+
+/**
+ * A {@link DependencyFilter} that filters dependencies based on the jar type declared in
+ * their manifest.
+ *
+ * @author Andy Wilkinson
+ */
+class JarTypeFilter extends DependencyFilter {
+
+ private static final Set EXCLUDED_JAR_TYPES = Collections
+ .unmodifiableSet(new HashSet<>(Arrays.asList("annotation-processor", "dependencies-starter")));
+
+ JarTypeFilter() {
+ super(Collections.emptyList());
+ }
+
+ @Override
+ protected boolean filter(Artifact artifact) {
+ try (JarFile jarFile = new JarFile(artifact.getFile())) {
+ String jarType = jarFile.getManifest().getMainAttributes().getValue("Spring-Boot-Jar-Type");
+ return jarType != null && EXCLUDED_JAR_TYPES.contains(jarType);
+ }
+ catch (IOException ex) {
+ return false;
+ }
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/DependencyFilterMojoTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/DependencyFilterMojoTests.java
index d09eb17284..f901743e43 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/DependencyFilterMojoTests.java
+++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/DependencyFilterMojoTests.java
@@ -16,17 +16,25 @@
package org.springframework.boot.maven;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
+import java.util.UUID;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
@@ -39,6 +47,9 @@ import static org.mockito.Mockito.mock;
*/
class DependencyFilterMojoTests {
+ @TempDir
+ static Path temp;
+
@Test
void filterDependencies() throws MojoExecutionException {
TestableDependencyFilterMojo mojo = new TestableDependencyFilterMojo(Collections.emptyList(), "com.foo");
@@ -97,20 +108,50 @@ class DependencyFilterMojoTests {
assertThat(artifacts).containsExactly(one, three, four);
}
+ @Test
+ void excludeByJarType() throws MojoExecutionException {
+ TestableDependencyFilterMojo mojo = new TestableDependencyFilterMojo(Collections.emptyList(), "");
+ Artifact one = createArtifact("com.foo", "one", null, "dependencies-starter");
+ Artifact two = createArtifact("com.bar", "two");
+ Set artifacts = mojo.filterDependencies(one, two);
+ assertThat(artifacts).containsExactly(two);
+ }
+
private static Artifact createArtifact(String groupId, String artifactId) {
return createArtifact(groupId, artifactId, null);
}
private static Artifact createArtifact(String groupId, String artifactId, String scope) {
+ return createArtifact(groupId, artifactId, scope, null);
+ }
+
+ private static Artifact createArtifact(String groupId, String artifactId, String scope, String jarType) {
Artifact a = mock(Artifact.class);
given(a.getGroupId()).willReturn(groupId);
given(a.getArtifactId()).willReturn(artifactId);
if (scope != null) {
given(a.getScope()).willReturn(scope);
}
+ given(a.getFile()).willReturn(createArtifactFile(jarType));
return a;
}
+ private static File createArtifactFile(String jarType) {
+ Path jarPath = temp.resolve(UUID.randomUUID().toString() + ".jar");
+ Manifest manifest = new Manifest();
+ manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
+ if (jarType != null) {
+ manifest.getMainAttributes().putValue("Spring-Boot-Jar-Type", jarType);
+ }
+ try {
+ new JarOutputStream(new FileOutputStream(jarPath.toFile()), manifest).close();
+ }
+ catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ return jarPath.toFile();
+ }
+
private static final class TestableDependencyFilterMojo extends AbstractDependencyFilterMojo {
private final ArtifactsFilter[] additionalFilters;
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/JarTypeFilterTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/JarTypeFilterTests.java
new file mode 100644
index 0000000000..ffd929bb7d
--- /dev/null
+++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/JarTypeFilterTests.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012-2020 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.maven;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import org.apache.maven.artifact.Artifact;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.mock;
+
+/**
+ * Tests for {@link JarTypeFilter}.
+ *
+ * @author Andy Wilkinson
+ */
+class JarTypeFilterTests {
+
+ @TempDir
+ Path temp;
+
+ @Test
+ void whenArtifactHasNoJarTypeThenItIsIncluded() {
+ assertThat(new JarTypeFilter().filter(createArtifact(null))).isFalse();
+ }
+
+ @Test
+ void whenArtifactHasJarTypeThatIsNotExcludedThenItIsIncluded() {
+ assertThat(new JarTypeFilter().filter(createArtifact("something-included"))).isFalse();
+ }
+
+ @Test
+ void whenArtifactHasDependenciesStarterJarTypeThenItIsExcluded() {
+ assertThat(new JarTypeFilter().filter(createArtifact("dependencies-starter"))).isTrue();
+ }
+
+ @Test
+ void whenArtifactHasAnnotationProcessorJarTypeThenItIsExcluded() {
+ assertThat(new JarTypeFilter().filter(createArtifact("annotation-processor"))).isTrue();
+ }
+
+ private Artifact createArtifact(String jarType) {
+ Path jarPath = this.temp.resolve("test.jar");
+ Manifest manifest = new Manifest();
+ manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
+ if (jarType != null) {
+ manifest.getMainAttributes().putValue("Spring-Boot-Jar-Type", jarType);
+ }
+ try {
+ new JarOutputStream(new FileOutputStream(jarPath.toFile()), manifest).close();
+ }
+ catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ Artifact artifact = mock(Artifact.class);
+ given(artifact.getFile()).willReturn(jarPath.toFile());
+ return artifact;
+ }
+
+}