From 670d1672de85513f2f19b67c343b1b1673361c68 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 14 Oct 2021 14:26:02 -0700 Subject: [PATCH 1/3] Revert "Remove unnecessary bind-api dependency from test starter" This reverts commit 9867651024b095760366a5e0f8282af89fca47d5. See gh-28085 --- .../spring-boot-starters/spring-boot-starter-test/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-boot-project/spring-boot-starters/spring-boot-starter-test/build.gradle b/spring-boot-project/spring-boot-starters/spring-boot-starter-test/build.gradle index 6e5d4e409f..12ba82f587 100644 --- a/spring-boot-project/spring-boot-starters/spring-boot-starter-test/build.gradle +++ b/spring-boot-project/spring-boot-starters/spring-boot-starter-test/build.gradle @@ -9,6 +9,7 @@ dependencies { api(project(":spring-boot-project:spring-boot-test")) api(project(":spring-boot-project:spring-boot-test-autoconfigure")) api("com.jayway.jsonpath:json-path") + api("jakarta.xml.bind:jakarta.xml.bind-api") api("org.assertj:assertj-core") api("org.hamcrest:hamcrest") api("org.junit.jupiter:junit-jupiter") From e95b0b5257a61cea2cb27bdcd8f052b703ab70da Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 14 Oct 2021 17:37:48 -0700 Subject: [PATCH 2/3] Polish --- ...heckClasspathForUnnecessaryExclusions.java | 85 ++++++++++++------- 1 file changed, 54 insertions(+), 31 deletions(-) diff --git a/buildSrc/src/main/java/org/springframework/boot/build/classpath/CheckClasspathForUnnecessaryExclusions.java b/buildSrc/src/main/java/org/springframework/boot/build/classpath/CheckClasspathForUnnecessaryExclusions.java index 7270812fe4..c03f7fae9c 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/classpath/CheckClasspathForUnnecessaryExclusions.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/classpath/CheckClasspathForUnnecessaryExclusions.java @@ -38,6 +38,7 @@ import org.gradle.api.artifacts.ExcludeRule; import org.gradle.api.artifacts.ModuleDependency; import org.gradle.api.artifacts.component.ModuleComponentIdentifier; import org.gradle.api.artifacts.dsl.DependencyHandler; +import org.gradle.api.artifacts.result.ResolvedArtifactResult; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.TaskAction; @@ -48,6 +49,9 @@ import org.gradle.api.tasks.TaskAction; */ public class CheckClasspathForUnnecessaryExclusions extends DefaultTask { + private static final Map SPRING_BOOT_DEPENDENCIES_PROJECT = Collections.singletonMap("path", + ":spring-boot-project:spring-boot-dependencies"); + private final Map> exclusionsByDependencyId = new TreeMap<>(); private final Map dependencyById = new HashMap<>(); @@ -63,27 +67,31 @@ public class CheckClasspathForUnnecessaryExclusions extends DefaultTask { ConfigurationContainer configurations) { this.dependencyHandler = getProject().getDependencies(); this.configurations = getProject().getConfigurations(); - this.platform = this.dependencyHandler.create(this.dependencyHandler.platform(this.dependencyHandler - .project(Collections.singletonMap("path", ":spring-boot-project:spring-boot-dependencies")))); + this.platform = this.dependencyHandler.create( + this.dependencyHandler.platform(this.dependencyHandler.project(SPRING_BOOT_DEPENDENCIES_PROJECT))); getOutputs().upToDateWhen((task) -> true); } public void setClasspath(Configuration classpath) { this.exclusionsByDependencyId.clear(); this.dependencyById.clear(); - classpath.getAllDependencies().all((dependency) -> { - if (dependency instanceof ModuleDependency) { - String dependencyId = dependency.getGroup() + ":" + dependency.getName(); - Set excludeRules = ((ModuleDependency) dependency).getExcludeRules(); - TreeSet exclusions = excludeRules.stream() - .map((rule) -> rule.getGroup() + ":" + rule.getModule()) - .collect(Collectors.toCollection(TreeSet::new)); - this.exclusionsByDependencyId.put(dependencyId, exclusions); - if (!exclusions.isEmpty()) { - this.dependencyById.put(dependencyId, getProject().getDependencies().create(dependencyId)); - } - } - }); + classpath.getAllDependencies().all(this::processDependency); + } + + private void processDependency(Dependency dependency) { + if (dependency instanceof ModuleDependency) { + processDependency((ModuleDependency) dependency); + } + } + + private void processDependency(ModuleDependency dependency) { + String dependencyId = getId(dependency); + TreeSet exclusions = dependency.getExcludeRules().stream().map(this::getId) + .collect(Collectors.toCollection(TreeSet::new)); + this.exclusionsByDependencyId.put(dependencyId, exclusions); + if (!exclusions.isEmpty()) { + this.dependencyById.put(dependencyId, getProject().getDependencies().create(dependencyId)); + } } @Input @@ -94,33 +102,48 @@ public class CheckClasspathForUnnecessaryExclusions extends DefaultTask { @TaskAction public void checkForUnnecessaryExclusions() { Map> unnecessaryExclusions = new HashMap<>(); - for (Entry> entry : this.exclusionsByDependencyId.entrySet()) { - String dependencyId = entry.getKey(); - Set exclusions = entry.getValue(); + this.exclusionsByDependencyId.forEach((dependencyId, exclusions) -> { if (!exclusions.isEmpty()) { Dependency toCheck = this.dependencyById.get(dependencyId); List dependencies = this.configurations.detachedConfiguration(toCheck, this.platform) - .getIncoming().getArtifacts().getArtifacts().stream().map((artifact) -> { - ModuleComponentIdentifier id = (ModuleComponentIdentifier) artifact.getId() - .getComponentIdentifier(); - return id.getGroup() + ":" + id.getModule(); - }).collect(Collectors.toList()); + .getIncoming().getArtifacts().getArtifacts().stream().map(this::getId) + .collect(Collectors.toList()); exclusions.removeAll(dependencies); if (!exclusions.isEmpty()) { unnecessaryExclusions.put(dependencyId, exclusions); } } - } + }); if (!unnecessaryExclusions.isEmpty()) { - StringBuilder message = new StringBuilder("Unnecessary exclusions detected:"); - for (Entry> entry : unnecessaryExclusions.entrySet()) { - message.append(String.format("%n %s", entry.getKey())); - for (String exclusion : entry.getValue()) { - message.append(String.format("%n %s", exclusion)); - } + throw new GradleException(getExceptionMessage(unnecessaryExclusions)); + } + } + + private String getExceptionMessage(Map> unnecessaryExclusions) { + StringBuilder message = new StringBuilder("Unnecessary exclusions detected:"); + for (Entry> entry : unnecessaryExclusions.entrySet()) { + message.append(String.format("%n %s", entry.getKey())); + for (String exclusion : entry.getValue()) { + message.append(String.format("%n %s", exclusion)); } - throw new GradleException(message.toString()); } + return message.toString(); + } + + private String getId(ResolvedArtifactResult artifact) { + return getId((ModuleComponentIdentifier) artifact.getId().getComponentIdentifier()); + } + + private String getId(ModuleDependency dependency) { + return dependency.getGroup() + ":" + dependency.getName(); + } + + private String getId(ExcludeRule rule) { + return rule.getGroup() + ":" + rule.getModule(); + } + + private String getId(ModuleComponentIdentifier identifier) { + return identifier.getGroup() + ":" + identifier.getModule(); } } From 8e704aab48bc3d3f80cb366584c78409a0330bac Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 14 Oct 2021 17:38:05 -0700 Subject: [PATCH 3/3] Restore 'javax.xml.bind:jaxb-api' exclusion Restore the 'javax.xml.bind:jaxb-api' exclusion from `xmlunit-core` which is actually required when using Maven on Java 9+. The `CheckClasspathForUnnecessaryExclusions` cannot deal with profile specific dependencies so an exception has been hard coded. See gh-28332 --- .../classpath/CheckClasspathForUnnecessaryExclusions.java | 7 +++++++ .../spring-boot-starter-test/build.gradle | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/buildSrc/src/main/java/org/springframework/boot/build/classpath/CheckClasspathForUnnecessaryExclusions.java b/buildSrc/src/main/java/org/springframework/boot/build/classpath/CheckClasspathForUnnecessaryExclusions.java index c03f7fae9c..797f2df3fb 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/classpath/CheckClasspathForUnnecessaryExclusions.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/classpath/CheckClasspathForUnnecessaryExclusions.java @@ -109,6 +109,7 @@ public class CheckClasspathForUnnecessaryExclusions extends DefaultTask { .getIncoming().getArtifacts().getArtifacts().stream().map(this::getId) .collect(Collectors.toList()); exclusions.removeAll(dependencies); + removeProfileExclusions(dependencyId, exclusions); if (!exclusions.isEmpty()) { unnecessaryExclusions.put(dependencyId, exclusions); } @@ -119,6 +120,12 @@ public class CheckClasspathForUnnecessaryExclusions extends DefaultTask { } } + private void removeProfileExclusions(String dependencyId, Set exclusions) { + if ("org.xmlunit:xmlunit-core".equals(dependencyId)) { + exclusions.remove("javax.xml.bind:jaxb-api"); + } + } + private String getExceptionMessage(Map> unnecessaryExclusions) { StringBuilder message = new StringBuilder("Unnecessary exclusions detected:"); for (Entry> entry : unnecessaryExclusions.entrySet()) { diff --git a/spring-boot-project/spring-boot-starters/spring-boot-starter-test/build.gradle b/spring-boot-project/spring-boot-starters/spring-boot-starter-test/build.gradle index 12ba82f587..74ba78aab0 100644 --- a/spring-boot-project/spring-boot-starters/spring-boot-starter-test/build.gradle +++ b/spring-boot-project/spring-boot-starters/spring-boot-starter-test/build.gradle @@ -18,5 +18,7 @@ dependencies { api("org.skyscreamer:jsonassert") api("org.springframework:spring-core") api("org.springframework:spring-test") - api("org.xmlunit:xmlunit-core") + api("org.xmlunit:xmlunit-core") { + exclude group: "javax.xml.bind", module: "jaxb-api" + } }