diff --git a/buildSrc/src/main/java/org/springframework/boot/build/bom/BomExtension.java b/buildSrc/src/main/java/org/springframework/boot/build/bom/BomExtension.java index 0fc2633635a..114b19280f5 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/bom/BomExtension.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/bom/BomExtension.java @@ -40,9 +40,11 @@ import org.gradle.api.plugins.JavaPlatformPlugin; import org.springframework.boot.build.bom.Library.Exclusion; import org.springframework.boot.build.bom.Library.Group; +import org.springframework.boot.build.bom.Library.ImportedBom; import org.springframework.boot.build.bom.Library.LibraryVersion; import org.springframework.boot.build.bom.Library.Link; import org.springframework.boot.build.bom.Library.Module; +import org.springframework.boot.build.bom.Library.PermittedDependency; import org.springframework.boot.build.bom.Library.ProhibitedVersion; import org.springframework.boot.build.bom.Library.VersionAlignment; import org.springframework.boot.build.bom.bomr.version.DependencyVersion; @@ -152,8 +154,8 @@ public class BomExtension { for (Module module : group.getModules()) { addModule(library, dependencies, versionProperty, group, module); } - for (String bomImport : group.getBoms()) { - addBomImport(library, dependencies, versionProperty, group, bomImport); + for (ImportedBom bomImport : group.getBoms()) { + addBomImport(library, dependencies, versionProperty, group, bomImport.name()); } } } @@ -176,6 +178,8 @@ public class BomExtension { public static class LibraryHandler { + private final Project project; + private final List groups = new ArrayList<>(); private final List prohibitedVersions = new ArrayList<>(); @@ -194,6 +198,7 @@ public class BomExtension { @Inject public LibraryHandler(Project project, String version) { + this.project = project; this.version = version; this.alignWith = project.getObjects().newInstance(AlignWithHandler.class); } @@ -211,7 +216,7 @@ public class BomExtension { } public void group(String id, Action action) { - GroupHandler groupHandler = new GroupHandler(id); + GroupHandler groupHandler = this.project.getObjects().newInstance(GroupHandler.class, id); action.execute(groupHandler); this.groups .add(new Group(groupHandler.id, groupHandler.modules, groupHandler.plugins, groupHandler.imports)); @@ -290,16 +295,17 @@ public class BomExtension { } - public class GroupHandler extends GroovyObjectSupport { + public static class GroupHandler extends GroovyObjectSupport { private final String id; private List modules = new ArrayList<>(); - private List imports = new ArrayList<>(); + private List imports = new ArrayList<>(); private List plugins = new ArrayList<>(); + @Inject public GroupHandler(String id) { this.id = id; } @@ -310,8 +316,14 @@ public class BomExtension { .toList(); } - public void setImports(List imports) { - this.imports = imports; + public void bom(String bom) { + this.imports.add(new ImportedBom(bom)); + } + + public void bom(String bom, Action action) { + ImportBomHandler handler = new ImportBomHandler(); + action.execute(handler); + this.imports.add(new ImportedBom(bom, handler.permittedDependencies)); } public void setPlugins(List plugins) { @@ -353,6 +365,17 @@ public class BomExtension { } + public class ImportBomHandler { + + private final List permittedDependencies = new ArrayList<>(); + + public void permit(String allowed) { + String[] components = allowed.split(":"); + this.permittedDependencies.add(new PermittedDependency(components[0], components[1])); + } + + } + } public static class AlignWithHandler { diff --git a/buildSrc/src/main/java/org/springframework/boot/build/bom/BomResolver.java b/buildSrc/src/main/java/org/springframework/boot/build/bom/BomResolver.java index b195b9f0487..ff02527086e 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/bom/BomResolver.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/bom/BomResolver.java @@ -42,6 +42,7 @@ import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.springframework.boot.build.bom.Library.Group; +import org.springframework.boot.build.bom.Library.ImportedBom; import org.springframework.boot.build.bom.Library.Link; import org.springframework.boot.build.bom.Library.Module; import org.springframework.boot.build.bom.ResolvedBom.Bom; @@ -84,9 +85,9 @@ class BomResolver { Id id = new Id(group.getId(), module.getName(), library.getVersion().getVersion().toString()); managedDependencies.add(id); } - for (String imported : group.getBoms()) { + for (ImportedBom imported : group.getBoms()) { Bom bom = bomFrom(resolveBom( - "%s:%s:%s".formatted(group.getId(), imported, library.getVersion().getVersion()))); + "%s:%s:%s".formatted(group.getId(), imported.name(), library.getVersion().getVersion()))); imports.add(bom); } } diff --git a/buildSrc/src/main/java/org/springframework/boot/build/bom/CheckBom.java b/buildSrc/src/main/java/org/springframework/boot/build/bom/CheckBom.java index ee5ad1b3862..585fd149fb0 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/bom/CheckBom.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/bom/CheckBom.java @@ -17,7 +17,11 @@ package org.springframework.boot.build.bom; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.TreeSet; @@ -42,7 +46,9 @@ import org.gradle.api.tasks.PathSensitivity; import org.gradle.api.tasks.TaskAction; import org.springframework.boot.build.bom.Library.Group; +import org.springframework.boot.build.bom.Library.ImportedBom; import org.springframework.boot.build.bom.Library.Module; +import org.springframework.boot.build.bom.Library.PermittedDependency; import org.springframework.boot.build.bom.Library.ProhibitedVersion; import org.springframework.boot.build.bom.Library.VersionAlignment; import org.springframework.boot.build.bom.ResolvedBom.Bom; @@ -69,7 +75,8 @@ public abstract class CheckBom extends DefaultTask { Provider resolvedBom = getResolvedBomFile().map(RegularFile::getAsFile).map(ResolvedBom::readFrom); this.checks = List.of(new CheckExclusions(configurations, dependencies), new CheckProhibitedVersions(), new CheckVersionAlignment(), - new CheckDependencyManagementAlignment(resolvedBom, configurations, dependencies)); + new CheckDependencyManagementAlignment(resolvedBom, configurations, dependencies), + new CheckForUnwantedDependencyManagement(resolvedBom)); this.bom = bom; } @@ -241,31 +248,22 @@ public abstract class CheckBom extends DefaultTask { } - private static final class CheckDependencyManagementAlignment implements LibraryCheck { + private abstract static class ResolvedLibraryCheck implements LibraryCheck { private final Provider resolvedBom; - private final BomResolver bomResolver; - - private CheckDependencyManagementAlignment(Provider resolvedBom, - ConfigurationContainer configurations, DependencyHandler dependencies) { + private ResolvedLibraryCheck(Provider resolvedBom) { this.resolvedBom = resolvedBom; - this.bomResolver = new BomResolver(configurations, dependencies); } @Override public List check(Library library) { - List errors = new ArrayList<>(); - String alignsWithBom = library.getAlignsWithBom(); - if (alignsWithBom != null) { - Bom mavenBom = this.bomResolver - .resolveMavenBom(alignsWithBom + ":" + library.getVersion().getVersion()); - ResolvedLibrary resolvedLibrary = getResolvedLibrary(library); - checkDependencyManagementAlignment(resolvedLibrary, mavenBom, errors); - } - return errors; + ResolvedLibrary resolvedLibrary = getResolvedLibrary(library); + return check(library, resolvedLibrary); } + protected abstract List check(Library library, ResolvedLibrary resolvedLibrary); + private ResolvedLibrary getResolvedLibrary(Library library) { ResolvedBom resolvedBom = this.resolvedBom.get(); Optional resolvedLibrary = resolvedBom.libraries() @@ -278,6 +276,30 @@ public abstract class CheckBom extends DefaultTask { return resolvedLibrary.get(); } + } + + private static final class CheckDependencyManagementAlignment extends ResolvedLibraryCheck { + + private final BomResolver bomResolver; + + private CheckDependencyManagementAlignment(Provider resolvedBom, + ConfigurationContainer configurations, DependencyHandler dependencies) { + super(resolvedBom); + this.bomResolver = new BomResolver(configurations, dependencies); + } + + @Override + public List check(Library library, ResolvedLibrary resolvedLibrary) { + List errors = new ArrayList<>(); + String alignsWithBom = library.getAlignsWithBom(); + if (alignsWithBom != null) { + Bom mavenBom = this.bomResolver + .resolveMavenBom(alignsWithBom + ":" + library.getVersion().getVersion()); + checkDependencyManagementAlignment(resolvedLibrary, mavenBom, errors); + } + return errors; + } + private void checkDependencyManagementAlignment(ResolvedLibrary library, Bom mavenBom, List errors) { List managedByLibrary = library.managedDependencies(); List managedByBom = managedDependenciesOf(mavenBom); @@ -316,4 +338,108 @@ public abstract class CheckBom extends DefaultTask { } + private static final class CheckForUnwantedDependencyManagement extends ResolvedLibraryCheck { + + private CheckForUnwantedDependencyManagement(Provider resolvedBom) { + super(resolvedBom); + } + + @Override + public List check(Library library, ResolvedLibrary resolvedLibrary) { + Map> unwanted = findUnwantedDependencyManagement(library, resolvedLibrary); + List errors = new ArrayList<>(); + if (!unwanted.isEmpty()) { + StringBuilder error = new StringBuilder("Unwanted dependency management:"); + unwanted.forEach((bom, dependencies) -> { + error.append("%n - %s:".formatted(bom)); + error.append("%n - %s".formatted(String.join("\n - ", dependencies))); + }); + errors.add(error.toString()); + } + Map> unnecessary = findUnnecessaryPermittedDependencies(library, resolvedLibrary); + if (!unnecessary.isEmpty()) { + StringBuilder error = new StringBuilder("Dependencies permitted unnecessarily:"); + unnecessary.forEach((bom, dependencies) -> { + error.append("%n - %s:".formatted(bom)); + error.append("%n - %s".formatted(String.join("\n - ", dependencies))); + }); + errors.add(error.toString()); + } + return errors; + } + + private Map> findUnwantedDependencyManagement(Library library, + ResolvedLibrary resolvedLibrary) { + Map> unwanted = new LinkedHashMap<>(); + for (Bom bom : resolvedLibrary.importedBoms()) { + Set notPermitted = new TreeSet<>(); + Set managedDependencies = managedDependenciesOf(bom); + managedDependencies.stream() + .filter((dependency) -> unwanted(bom, dependency, findPermittedDependencies(library, bom))) + .map(Id::toString) + .forEach(notPermitted::add); + if (!notPermitted.isEmpty()) { + unwanted.put(bom.id().artifactId(), notPermitted); + } + } + return unwanted; + } + + private List findPermittedDependencies(Library library, Bom bom) { + for (Group group : library.getGroups()) { + for (ImportedBom importedBom : group.getBoms()) { + if (importedBom.name().equals(bom.id().artifactId()) && group.getId().equals(bom.id().groupId())) { + return importedBom.permittedDependencies(); + } + } + } + return Collections.emptyList(); + } + + private Set managedDependenciesOf(Bom bom) { + Set managedDependencies = new TreeSet<>(); + if (bom != null) { + managedDependencies.addAll(bom.managedDependencies()); + managedDependencies.addAll(managedDependenciesOf(bom.parent())); + for (Bom importedBom : bom.importedBoms()) { + managedDependencies.addAll(managedDependenciesOf(importedBom)); + } + } + return managedDependencies; + } + + private boolean unwanted(Bom bom, Id managedDependency, List permittedDependencies) { + if (bom.id().groupId().equals(managedDependency.groupId()) + || managedDependency.groupId().startsWith(bom.id().groupId() + ".")) { + return false; + } + for (PermittedDependency permittedDependency : permittedDependencies) { + if (permittedDependency.artifactId().equals(managedDependency.artifactId()) + && permittedDependency.groupId().equals(managedDependency.groupId())) { + return false; + } + } + return true; + } + + private Map> findUnnecessaryPermittedDependencies(Library library, + ResolvedLibrary resolvedLibrary) { + Map> unnecessary = new HashMap<>(); + for (Bom bom : resolvedLibrary.importedBoms()) { + Set permittedDependencies = findPermittedDependencies(library, bom).stream() + .map((dependency) -> dependency.groupId() + ":" + dependency.artifactId()) + .collect(Collectors.toCollection(TreeSet::new)); + Set dependencies = managedDependenciesOf(bom).stream() + .map((dependency) -> dependency.groupId() + ":" + dependency.artifactId()) + .collect(Collectors.toCollection(TreeSet::new)); + permittedDependencies.removeAll(dependencies); + if (!permittedDependencies.isEmpty()) { + unnecessary.put(bom.id().artifactId(), permittedDependencies); + } + } + return unnecessary; + } + + } + } diff --git a/buildSrc/src/main/java/org/springframework/boot/build/bom/Library.java b/buildSrc/src/main/java/org/springframework/boot/build/bom/Library.java index 6a99a434038..7c77d60485f 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/bom/Library.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/bom/Library.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 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. @@ -37,6 +37,7 @@ import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.result.DependencyResult; +import org.gradle.api.artifacts.result.ResolutionResult; import org.springframework.boot.build.bom.bomr.version.DependencyVersion; @@ -304,9 +305,9 @@ public class Library { private final List plugins; - private final List boms; + private final List boms; - public Group(String id, List modules, List plugins, List boms) { + public Group(String id, List modules, List plugins, List boms) { this.id = id; this.modules = modules; this.plugins = plugins; @@ -325,7 +326,7 @@ public class Library { return this.plugins; } - public List getBoms() { + public List getBoms() { return this.boms; } @@ -459,9 +460,8 @@ public class Library { Configuration alignmentConfiguration = this.project.getConfigurations() .detachedConfiguration(dependencies.toArray(new Dependency[0])); Map versions = new HashMap<>(); - for (DependencyResult dependency : alignmentConfiguration.getIncoming() - .getResolutionResult() - .getAllDependencies()) { + ResolutionResult resolutionResult = alignmentConfiguration.getIncoming().getResolutionResult(); + for (DependencyResult dependency : resolutionResult.getAllDependencies()) { versions.put(dependency.getFrom().getModuleVersion().getModule().toString(), dependency.getFrom().getModuleVersion().getVersion()); } @@ -516,7 +516,7 @@ public class Library { .flatMap((group) -> group.getBoms() .stream() .map((bom) -> this.project.getDependencies() - .platform(group.getId() + ":" + bom + ":" + manager.getVersion().getVersion()))) + .platform(group.getId() + ":" + bom.name() + ":" + manager.getVersion().getVersion()))) .toList(); } @@ -571,4 +571,16 @@ public class Library { } + public record ImportedBom(String name, List permittedDependencies) { + + public ImportedBom(String name) { + this(name, Collections.emptyList()); + } + + } + + public record PermittedDependency(String groupId, String artifactId) { + + } + } diff --git a/buildSrc/src/main/java/org/springframework/boot/build/bom/bomr/StandardLibraryUpdateResolver.java b/buildSrc/src/main/java/org/springframework/boot/build/bom/bomr/StandardLibraryUpdateResolver.java index adc16dd0c0d..28329e66f49 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/bom/bomr/StandardLibraryUpdateResolver.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/bom/bomr/StandardLibraryUpdateResolver.java @@ -31,6 +31,7 @@ import org.slf4j.LoggerFactory; import org.springframework.boot.build.bom.Library; import org.springframework.boot.build.bom.Library.Group; +import org.springframework.boot.build.bom.Library.ImportedBom; import org.springframework.boot.build.bom.Library.Module; import org.springframework.boot.build.bom.Library.VersionAlignment; import org.springframework.boot.build.bom.bomr.version.DependencyVersion; @@ -112,8 +113,9 @@ class StandardLibraryUpdateResolver implements LibraryUpdateResolver { moduleVersions.put(group.getId() + ":" + module.getName(), getLaterVersionsForModule(group.getId(), module.getName(), library)); } - for (String bom : group.getBoms()) { - moduleVersions.put(group.getId() + ":" + bom, getLaterVersionsForModule(group.getId(), bom, library)); + for (ImportedBom bom : group.getBoms()) { + moduleVersions.put(group.getId() + ":" + bom, + getLaterVersionsForModule(group.getId(), bom.name(), library)); } for (String plugin : group.getPlugins()) { moduleVersions.put(group.getId() + ":" + plugin, diff --git a/buildSrc/src/test/java/org/springframework/boot/build/bom/BomPluginIntegrationTests.java b/buildSrc/src/test/java/org/springframework/boot/build/bom/BomPluginIntegrationTests.java index d6baf87b889..ad86cc204e2 100644 --- a/buildSrc/src/test/java/org/springframework/boot/build/bom/BomPluginIntegrationTests.java +++ b/buildSrc/src/test/java/org/springframework/boot/build/bom/BomPluginIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 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. @@ -122,9 +122,7 @@ class BomPluginIntegrationTests { out.println("bom {"); out.println(" library('Jackson Bom', '2.10.0') {"); out.println(" group('com.fasterxml.jackson') {"); - out.println(" imports = ["); - out.println(" 'jackson-bom'"); - out.println(" ]"); + out.println(" bom('jackson-bom')"); out.println(" }"); out.println(" }"); out.println("}"); @@ -290,34 +288,6 @@ class BomPluginIntegrationTests { }); } - // @Test - // void versionAlignmentIsVerified() throws IOException { - // try (PrintWriter out = new PrintWriter(new FileWriter(this.buildFile))) { - // out.println("plugins {"); - // out.println(" id 'org.springframework.boot.bom'"); - // out.println("}"); - // out.println("bom {"); - // out.println(" library('OAuth2 OIDC SDK', '8.36.1') {"); - // out.println(" alignedWith('Spring Security') {"); - // out.println( - // " - // source('https://github.com/spring-projects/spring-security/blob/${libraryVersion}/config/gradle/dependency-locks/optional.lockfile')"); - // out.println(" pattern('com.nimbusds:oauth2-oidc-sdk:(.+)')"); - // out.println(" }"); - // out.println(" group('com.nimbusds') {"); - // out.println(" modules = ["); - // out.println(" 'oauth2-oidc-sdk'"); - // out.println(" ]"); - // out.println(" }"); - // out.println(" }"); - // out.println(" library('Spring Security', '5.4.7') {"); - // out.println(" }"); - // out.println("}"); - // } - // System.out.println(runGradle(DeployedPlugin.GENERATE_POM_TASK_NAME, - // "-s").getOutput()); - // } - private BuildResult runGradle(String... args) { return GradleRunner.create() .withDebug(true) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index c3830c5d786..07c4d2bb2b6 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -22,9 +22,7 @@ bom { exclude group: "commons-logging", module: "commons-logging" } ] - imports = [ - "activemq-bom" - ] + bom("activemq-bom") } links { site("https://activemq.apache.org") @@ -54,9 +52,9 @@ bom { } library("Artemis", "2.37.0") { group("org.apache.activemq") { - imports = [ - "artemis-bom" - ] + bom("artemis-bom") { + permit("org.apache.maven.plugin-tools:maven-plugin-annotations") + } } links { site("https://activemq.apache.org/components/artemis") @@ -80,9 +78,7 @@ bom { } library("AssertJ", "${assertjVersion}") { group("org.assertj") { - imports = [ - "assertj-bom" - ] + bom("assertj-bom") } links { site("https://assertj.github.io/doc") @@ -105,9 +101,9 @@ bom { } library("Zipkin Reporter", "3.4.3") { group("io.zipkin.reporter2") { - imports = [ - "zipkin-reporter-bom" - ] + bom("zipkin-reporter-bom") { + permit("io.zipkin.zipkin2:zipkin") + } } links { site("https://github.com/openzipkin/zipkin-reporter-java") @@ -116,9 +112,7 @@ bom { } library("Brave", "6.0.3") { group("io.zipkin.brave") { - imports = [ - "brave-bom" - ] + bom("brave-bom") } links { site("https://github.com/openzipkin/brave") @@ -183,9 +177,10 @@ bom { } library("Cassandra Driver", "4.18.1") { group("org.apache.cassandra") { - imports = [ - "java-driver-bom" - ] + bom("java-driver-bom") { + permit("com.datastax.oss:java-driver-shaded-guava") + permit("com.datastax.oss:native-protocol") + } modules = [ "java-driver-core" ] @@ -418,9 +413,19 @@ bom { } library("Glassfish JAXB", "4.0.5") { group("org.glassfish.jaxb") { - imports = [ - "jaxb-bom" - ] + bom("jaxb-bom") { + permit("com.sun.istack:istack-commons-runtime") + permit("com.sun.xml.bind:jaxb-core") + permit("com.sun.xml.bind:jaxb-impl") + permit("com.sun.xml.bind:jaxb-jxc") + permit("com.sun.xml.bind:jaxb-osgi") + permit("com.sun.xml.bind:jaxb-xjc") + permit("com.sun.xml.fastinfoset:FastInfoset") + permit("jakarta.activation:jakarta.activation-api") + permit("jakarta.xml.bind:jakarta.xml.bind-api") + permit("org.eclipse.angus:angus-activation") + permit("org.jvnet.staxex:stax-ex") + } } links { releaseNotes("https://github.com/eclipse-ee4j/jaxb-ri/releases/tag/{version}-RI") @@ -456,9 +461,7 @@ bom { } library("Groovy", "4.0.26") { group("org.apache.groovy") { - imports = [ - "groovy-bom" - ] + bom("groovy-bom") } links { site("https://groovy-lang.org") @@ -625,9 +628,7 @@ bom { } library("Infinispan", "15.0.14.Final") { group("org.infinispan") { - imports = [ - "infinispan-bom" - ] + bom("infinispan-bom") } links { site("https://infinispan.org") @@ -649,9 +650,7 @@ bom { } library("Jackson Bom", "${jacksonVersion}") { group("com.fasterxml.jackson") { - imports = [ - "jackson-bom" - ] + bom("jackson-bom") } links { releaseNotes("https://github.com/FasterXML/jackson/wiki/Jackson-Release-{version}") @@ -969,9 +968,7 @@ bom { } library("Jersey", "3.1.10") { group("org.glassfish.jersey") { - imports = [ - "jersey-bom" - ] + bom("jersey-bom") } links { site("https://github.com/eclipse-ee4j/jersey") @@ -988,14 +985,10 @@ bom { } library("Jetty", "12.0.18") { group("org.eclipse.jetty.ee10") { - imports = [ - "jetty-ee10-bom" - ] + bom("jetty-ee10-bom") } group("org.eclipse.jetty") { - imports = [ - "jetty-bom" - ] + bom("jetty-bom") } links { site("https://eclipse.dev/jetty") @@ -1082,9 +1075,7 @@ bom { } library("JUnit Jupiter", "${junitJupiterVersion}") { group("org.junit") { - imports = [ - "junit-bom" - ] + bom("junit-bom") } links { site("https://junit.org/junit5") @@ -1146,9 +1137,7 @@ bom { } library("Kotlin", "${kotlinVersion}") { group("org.jetbrains.kotlin") { - imports = [ - "kotlin-bom" - ] + bom("kotlin-bom") plugins = [ "kotlin-maven-plugin" ] @@ -1165,9 +1154,7 @@ bom { because "it requires Kotlin 2" } group("org.jetbrains.kotlinx") { - imports = [ - "kotlinx-coroutines-bom" - ] + bom("kotlinx-coroutines-bom") } links { site("https://github.com/Kotlin/kotlinx.coroutines") @@ -1180,9 +1167,7 @@ bom { because "it requires Kotlin 2" } group("org.jetbrains.kotlinx") { - imports = [ - "kotlinx-serialization-bom" - ] + bom("kotlinx-serialization-bom") } links { site("https://github.com/Kotlin/kotlinx.serialization") @@ -1220,9 +1205,16 @@ bom { } library("Log4j2", "2.24.3") { group("org.apache.logging.log4j") { - imports = [ - "log4j-bom" - ] + bom("log4j-bom") { + permit("biz.aQute.bnd:biz.aQute.bnd.annotation") + permit("com.github.spotbugs:spotbugs-annotations") + permit("org.apache.logging:logging-parent") + permit("org.apache.maven.plugin-tools:maven-plugin-annotations") + permit("org.jspecify:jspecify") + permit("org.osgi:org.osgi.annotation.bundle") + permit("org.osgi:org.osgi.annotation.versioning") + permit("org.osgi:osgi.annotation") + } } links { site("https://logging.apache.org/log4j") @@ -1449,9 +1441,7 @@ bom { exclude group: "javax.annotation", module: "javax.annotation-api" } ] - imports = [ - "micrometer-bom" - ] + bom("micrometer-bom") } links { site("https://micrometer.io") @@ -1468,9 +1458,7 @@ bom { library("Micrometer Tracing", "1.4.4") { considerSnapshots() group("io.micrometer") { - imports = [ - "micrometer-tracing-bom" - ] + bom("micrometer-tracing-bom") } links { site("https://micrometer.io") @@ -1482,9 +1470,7 @@ bom { } library("Mockito", "${mockitoVersion}") { group("org.mockito") { - imports = [ - "mockito-bom" - ] + bom("mockito-bom") } links { site("https://site.mockito.org") @@ -1581,9 +1567,7 @@ bom { } library("Netty", "4.1.119.Final") { group("io.netty") { - imports = [ - "netty-bom" - ] + bom("netty-bom") } links { site("https://netty.io") @@ -1592,9 +1576,7 @@ bom { } library("OpenTelemetry", "1.43.0") { group("io.opentelemetry") { - imports = [ - "opentelemetry-bom" - ] + bom("opentelemetry-bom") } links { site("https://github.com/open-telemetry/opentelemetry-java") @@ -1679,9 +1661,7 @@ bom { } library("Prometheus Client", "1.3.6") { group("io.prometheus") { - imports = [ - "prometheus-metrics-bom" - ] + bom("prometheus-metrics-bom") } links { site("https://github.com/prometheus/client_java") @@ -1691,9 +1671,7 @@ bom { } library("Prometheus Simpleclient", "0.16.0") { group("io.prometheus") { - imports = [ - "simpleclient_bom" - ] + bom("simpleclient_bom") } links { site("https://github.com/prometheus/client_java") @@ -1703,9 +1681,9 @@ bom { } library("Pulsar", "3.3.5") { group("org.apache.pulsar") { - imports = [ - "pulsar-bom" - ] + bom("pulsar-bom") { + permit("org.apache.maven.plugin-tools:maven-plugin-annotations") + } } links { site("https://pulsar.apache.org") @@ -1747,9 +1725,7 @@ bom { } library("QueryDSL", "5.1.0") { group("com.querydsl") { - imports = [ - "querydsl-bom" - ] + bom("querydsl-bom") } links { site("https://github.com/querydsl/querydsl") @@ -1879,9 +1855,9 @@ bom { considerSnapshots() calendarName = "Reactor" group("io.projectreactor") { - imports = [ - "reactor-bom" - ] + bom("reactor-bom") { + permit("org.reactivestreams:reactive-streams") + } } links { site("https://projectreactor.io") @@ -1890,9 +1866,7 @@ bom { } library("REST Assured", "5.5.1") { group("io.rest-assured") { - imports = [ - "rest-assured-bom" - ] + bom("rest-assured-bom") } links { javadoc("https://javadoc.io/doc/io.rest-assured/rest-assured/{version}", "io.restassured") @@ -1900,9 +1874,7 @@ bom { } library("RSocket", "1.1.5") { group("io.rsocket") { - imports = [ - "rsocket-bom" - ] + bom("rsocket-bom") } links { site("https://github.com/rsocket/rsocket-java") @@ -2020,9 +1992,7 @@ bom { } library("Selenium", "4.25.0") { group("org.seleniumhq.selenium") { - imports = [ - "selenium-bom" - ] + bom("selenium-bom") } links { site("https://www.selenium.dev") @@ -2079,9 +2049,7 @@ bom { library("Spring AMQP", "3.2.4") { considerSnapshots() group("org.springframework.amqp") { - imports = [ - "spring-amqp-bom" - ] + bom("spring-amqp-bom") } links { site("https://spring.io/projects/spring-amqp") @@ -2113,9 +2081,7 @@ bom { library("Spring Batch", "5.2.2") { considerSnapshots() group("org.springframework.batch") { - imports = [ - "spring-batch-bom" - ] + bom("spring-batch-bom") } links { site("https://spring.io/projects/spring-batch") @@ -2131,9 +2097,7 @@ bom { considerSnapshots() calendarName = "Spring Data Release" group("org.springframework.data") { - imports = [ - "spring-data-bom" - ] + bom("spring-data-bom") } links("spring-data") { site("https://spring.io/projects/spring-data") @@ -2144,9 +2108,7 @@ bom { library("Spring Framework", "${springFrameworkVersion}") { considerSnapshots() group("org.springframework") { - imports = [ - "spring-framework-bom" - ] + bom("spring-framework-bom") } links { site("https://spring.io/projects/spring-framework") @@ -2199,9 +2161,7 @@ bom { library("Spring Integration", "6.4.3") { considerSnapshots() group("org.springframework.integration") { - imports = [ - "spring-integration-bom" - ] + bom("spring-integration-bom") } links { site("https://spring.io/projects/spring-integration") @@ -2254,9 +2214,7 @@ bom { library("Spring Pulsar", "1.2.4") { considerSnapshots() group("org.springframework.pulsar") { - imports = [ - "spring-pulsar-bom" - ] + bom("spring-pulsar-bom") } links { site("https://spring.io/projects/spring-pulsar") @@ -2271,9 +2229,7 @@ bom { library("Spring RESTDocs", "3.0.3") { considerSnapshots() group("org.springframework.restdocs") { - imports = [ - "spring-restdocs-bom" - ] + bom("spring-restdocs-bom") } links { site("https://spring.io/projects/spring-restdocs") @@ -2301,9 +2257,7 @@ bom { library("Spring Security", "6.4.4") { considerSnapshots() group("org.springframework.security") { - imports = [ - "spring-security-bom" - ] + bom("spring-security-bom") } links { site("https://spring.io/projects/spring-security") @@ -2322,9 +2276,7 @@ bom { because "Spring Session switched to numeric version numbers" } group("org.springframework.session") { - imports = [ - "spring-session-bom" - ] + bom("spring-session-bom") } links { site("https://spring.io/projects/spring-session") @@ -2339,9 +2291,7 @@ bom { library("Spring WS", "4.0.12") { considerSnapshots() group("org.springframework.ws") { - imports = [ - "spring-ws-bom" - ] + bom("spring-ws-bom") } links("spring-webservices") { site("https://spring.io/projects/spring-ws") @@ -2366,9 +2316,7 @@ bom { } library("Testcontainers", "1.20.6") { group("org.testcontainers") { - imports = [ - "testcontainers-bom" - ] + bom("testcontainers-bom") } links { site("https://java.testcontainers.org") diff --git a/spring-boot-project/spring-boot-parent/build.gradle b/spring-boot-project/spring-boot-parent/build.gradle index 559fc855ee0..9ea9755ef01 100644 --- a/spring-boot-project/spring-boot-parent/build.gradle +++ b/spring-boot-project/spring-boot-parent/build.gradle @@ -64,9 +64,9 @@ bom { } library("Janino", "3.1.10") { group("org.codehaus.janino") { - imports = [ - "janino" - ] + bom("janino") { + permit("junit:junit") + } } } library("JLine", "2.11") {