Exclude starter jars when running and packaging with Gradle

This commit updates the Gradle Plugin to filter dependencies based on
the Spring-Boot-Jar-Type entry in their manifest. Jars with a
Spring-Boot-Jar-Type of dependencies-starter are excluded. Unlike the
Maven plugin, jars with a type of annotation-processor are not
excluded. It is not necessary with Gradle as use of the
annotationProcessor configuration for such dependencies already ensures
that they are not included.

See gh-22036
This commit is contained in:
Andy Wilkinson
2020-09-10 14:07:45 +01:00
parent e743d5fe66
commit 143d19754b
8 changed files with 187 additions and 3 deletions

View File

@@ -17,9 +17,14 @@
package org.springframework.boot.gradle.tasks.bundling;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.function.Consumer;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.stream.Stream;
import org.gradle.testkit.runner.InvalidRunnerConfigurationException;
@@ -172,4 +177,36 @@ abstract class AbstractBootArchiveIntegrationTests {
}
}
@TestTemplate
void jarTypeFilteringIsApplied() throws IOException {
File flatDirRepository = new File(this.gradleBuild.getProjectDir(), "repository");
createDependenciesStarterJar(new File(flatDirRepository, "starter.jar"));
createStandardJar(new File(flatDirRepository, "standard.jar"));
assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName).getOutcome())
.isEqualTo(TaskOutcome.SUCCESS);
try (JarFile jarFile = new JarFile(new File(this.gradleBuild.getProjectDir(), "build/libs").listFiles()[0])) {
Stream<String> libEntryNames = jarFile.stream().filter((entry) -> !entry.isDirectory())
.map(JarEntry::getName).filter((name) -> name.startsWith(this.libPath));
assertThat(libEntryNames).containsExactly(this.libPath + "standard.jar");
}
}
private void createStandardJar(File location) throws IOException {
createJar(location, (attributes) -> {
});
}
private void createDependenciesStarterJar(File location) throws IOException {
createJar(location, (attributes) -> attributes.putValue("Spring-Boot-Jar-Type", "dependencies-starter"));
}
private void createJar(File location, Consumer<Attributes> attributesConfigurer) throws IOException {
location.getParentFile().mkdirs();
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
attributesConfigurer.accept(attributes);
new JarOutputStream(new FileOutputStream(location), manifest).close();
}
}

View File

@@ -17,7 +17,12 @@
package org.springframework.boot.gradle.tasks.run;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.function.Consumer;
import java.util.jar.Attributes;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import org.gradle.api.JavaVersion;
import org.gradle.testkit.runner.BuildResult;
@@ -120,6 +125,17 @@ class BootRunIntegrationTests {
}
}
@TestTemplate
void jarTypeFilteringIsAppliedToTheClasspath() throws IOException {
copyClasspathApplication();
File flatDirRepository = new File(this.gradleBuild.getProjectDir(), "repository");
createDependenciesStarterJar(new File(flatDirRepository, "starter.jar"));
createStandardJar(new File(flatDirRepository, "standard.jar"));
BuildResult result = this.gradleBuild.build("bootRun");
assertThat(result.task(":bootRun").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(result.getOutput()).contains("standard.jar").doesNotContain("starter.jar");
}
private void copyClasspathApplication() throws IOException {
copyApplication("classpath");
}
@@ -138,4 +154,22 @@ class BootRunIntegrationTests {
return new File(this.gradleBuild.getProjectDir(), path).getCanonicalPath();
}
private void createStandardJar(File location) throws IOException {
createJar(location, (attributes) -> {
});
}
private void createDependenciesStarterJar(File location) throws IOException {
createJar(location, (attributes) -> attributes.putValue("Spring-Boot-Jar-Type", "dependencies-starter"));
}
private void createJar(File location, Consumer<Attributes> attributesConfigurer) throws IOException {
location.getParentFile().mkdirs();
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
attributesConfigurer.accept(attributes);
new JarOutputStream(new FileOutputStream(location), manifest).close();
}
}