From fcb2210a87b41eb24cd0213448cac6a96062284e Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 14 Apr 2021 00:02:44 -0700 Subject: [PATCH] Include optional shade plugin in published pom Update `MavenPublishingConventions` to add a new `mavenOptional` feature that allows us to declare optional dependencies that are also published in the generated POM. This change allows us to include the maven-shade-plugin in the spring-boot-maven-plugin POM which fixes an issue with Eclipse m2e. Fixes gh-21992 --- .../build/MavenPublishingConventions.java | 31 +++++++++-- .../spring-boot-maven-plugin/build.gradle | 2 +- .../maven/EclipseM2eIntegrationTests.java | 54 +++++++++++++++++++ 3 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/EclipseM2eIntegrationTests.java diff --git a/buildSrc/src/main/java/org/springframework/boot/build/MavenPublishingConventions.java b/buildSrc/src/main/java/org/springframework/boot/build/MavenPublishingConventions.java index 39a621bd0aa..c10a7ef50ed 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/MavenPublishingConventions.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/MavenPublishingConventions.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. @@ -19,7 +19,10 @@ package org.springframework.boot.build; import org.apache.maven.artifact.repository.MavenArtifactRepository; import org.gradle.api.Project; import org.gradle.api.attributes.Usage; +import org.gradle.api.component.AdhocComponentWithVariants; +import org.gradle.api.component.ConfigurationVariantDetails; import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.plugins.JavaPluginExtension; import org.gradle.api.publish.PublishingExtension; import org.gradle.api.publish.maven.MavenPom; @@ -49,8 +52,6 @@ import org.gradle.api.publish.maven.plugins.MavenPublishPlugin; * * * - *

- * * @author Andy Wilkinson * @author Christoph Dreis * @author Mike Smithson @@ -80,6 +81,7 @@ class MavenPublishingConventions { customizePom(publication.getPom(), project); project.getPlugins().withType(JavaPlugin.class) .all((javaPlugin) -> customizeJavaMavenPublication(publication, project)); + suppressMavenOptionalFeatureWarnings(publication); } private void customizePom(MavenPom pom, Project project) { @@ -98,12 +100,35 @@ class MavenPublishingConventions { } private void customizeJavaMavenPublication(MavenPublication publication, Project project) { + addMavenOptionalFeature(project); publication.versionMapping((strategy) -> strategy.usage(Usage.JAVA_API, (mappingStrategy) -> mappingStrategy .fromResolutionOf(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME))); publication.versionMapping((strategy) -> strategy.usage(Usage.JAVA_RUNTIME, (mappingStrategy) -> mappingStrategy.fromResolutionResult())); } + /** + * Add a feature that allows maven plugins to declare optional dependencies that + * appear in the POM. This is required to make m2e in Eclipse happy. + * @param project the project to add the feature to + */ + private void addMavenOptionalFeature(Project project) { + JavaPluginExtension extension = project.getExtensions().getByType(JavaPluginExtension.class); + JavaPluginConvention convention = project.getConvention().getPlugin(JavaPluginConvention.class); + extension.registerFeature("mavenOptional", + (feature) -> feature.usingSourceSet(convention.getSourceSets().getByName("main"))); + AdhocComponentWithVariants javaComponent = (AdhocComponentWithVariants) project.getComponents() + .findByName("java"); + javaComponent.addVariantsFromConfiguration( + project.getConfigurations().findByName("mavenOptionalRuntimeElements"), + ConfigurationVariantDetails::mapToOptional); + } + + private void suppressMavenOptionalFeatureWarnings(MavenPublication publication) { + publication.suppressPomMetadataWarningsFor("mavenOptionalApiElements"); + publication.suppressPomMetadataWarningsFor("mavenOptionalRuntimeElements"); + } + private void customizeOrganization(MavenPomOrganization organization) { organization.getName().set("Pivotal Software, Inc."); organization.getUrl().set("https://spring.io"); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle index 769a6cc499e..b337aa122c2 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle @@ -32,7 +32,7 @@ dependencies { intTestImplementation("org.junit.jupiter:junit-jupiter") intTestImplementation("org.testcontainers:testcontainers") - optional("org.apache.maven.plugins:maven-shade-plugin") + mavenOptionalImplementation("org.apache.maven.plugins:maven-shade-plugin") runtimeOnly("org.sonatype.plexus:plexus-build-api") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/EclipseM2eIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/EclipseM2eIntegrationTests.java new file mode 100644 index 00000000000..ba056a5c63a --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/EclipseM2eIntegrationTests.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012-2021 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.File; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Comparator; + +import org.junit.jupiter.api.Test; + +import org.springframework.util.FileCopyUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests to check that our plugin works well with Eclipse m2e. + * + * @author Phillip Webb + */ +public class EclipseM2eIntegrationTests { + + @Test // gh-21992 + void pluginPomIncludesOptionalShadeDependency() throws Exception { + SpringBootDependenciesBom bom = new SpringBootDependenciesBom(); + String version = bom.get("version"); + File repository = new File("build/int-test-maven-repository"); + File pluginDirectory = new File(repository, "org/springframework/boot/spring-boot-maven-plugin/" + version); + File[] pomFiles = pluginDirectory.listFiles(this::isPomFile); + Arrays.sort(pomFiles, Comparator.comparing(File::getName)); + File pomFile = pomFiles[pomFiles.length - 1]; + String pomContent = new String(FileCopyUtils.copyToByteArray(pomFile), StandardCharsets.UTF_8); + assertThat(pomContent).contains("maven-shade-plugin"); + } + + private boolean isPomFile(File file) { + return file.getName().endsWith(".pom"); + } + +}