Merge branch '3.5.x'

Closes gh-48110
This commit is contained in:
Andy Wilkinson
2025-11-13 10:19:47 +00:00
5 changed files with 147 additions and 31 deletions
@@ -0,0 +1,121 @@
/*
* Copyright 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.
* 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.build.context.properties;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.gradle.api.DefaultTask;
import org.gradle.api.Task;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.VerificationException;
/**
* {@link Task} that checks aggregated Spring configuration metadata.
*
* @author Andy Wilkinson
*/
public abstract class CheckAggregatedSpringConfigurationMetadata extends DefaultTask {
private FileCollection configurationPropertyMetadata;
@OutputFile
public abstract RegularFileProperty getReportLocation();
@InputFiles
@PathSensitive(PathSensitivity.RELATIVE)
public FileCollection getConfigurationPropertyMetadata() {
return this.configurationPropertyMetadata;
}
public void setConfigurationPropertyMetadata(FileCollection configurationPropertyMetadata) {
this.configurationPropertyMetadata = configurationPropertyMetadata;
}
@TaskAction
void check() throws IOException {
Report report = createReport();
File reportFile = getReportLocation().get().getAsFile();
Files.write(reportFile.toPath(), report, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
if (report.hasProblems()) {
throw new VerificationException(
"Problems found in aggregated Spring configuration metadata. See " + reportFile + " for details.");
}
}
private Report createReport() {
ConfigurationProperties configurationProperties = ConfigurationProperties
.fromFiles(this.configurationPropertyMetadata);
Set<String> propertyNames = configurationProperties.stream()
.map(ConfigurationProperty::getName)
.collect(Collectors.toSet());
List<ConfigurationProperty> missingReplacement = configurationProperties.stream()
.filter(ConfigurationProperty::isDeprecated)
.filter((deprecated) -> {
String replacement = deprecated.getDeprecation().replacement();
return replacement != null && !propertyNames.contains(replacement);
})
.toList();
return new Report(missingReplacement);
}
private static final class Report implements Iterable<String> {
private final List<ConfigurationProperty> propertiesWithMissingReplacement;
private Report(List<ConfigurationProperty> propertiesWithMissingReplacement) {
this.propertiesWithMissingReplacement = propertiesWithMissingReplacement;
}
private boolean hasProblems() {
return !this.propertiesWithMissingReplacement.isEmpty();
}
@Override
public Iterator<String> iterator() {
List<String> lines = new ArrayList<>();
if (this.propertiesWithMissingReplacement.isEmpty()) {
lines.add("No problems found.");
}
else {
lines.add("The following properties have a replacement that does not exist:");
lines.add("");
lines.addAll(this.propertiesWithMissingReplacement.stream()
.map((property) -> "\t" + property.getName() + " (replacement "
+ property.getDeprecation().replacement() + ")")
.toList());
}
lines.add("");
return lines.iterator();
}
}
}
@@ -370,6 +370,12 @@ def configurationPropertiesMetadataAggregate = aggregates.create("configurationP
usage = "configuration-properties-metadata"
}
def checkAggregatedSpringConfigurationMetadata = tasks.register("checkAggregatedSpringConfigurationMetadata", org.springframework.boot.build.context.properties.CheckAggregatedSpringConfigurationMetadata) {
configurationPropertyMetadata = configurationPropertiesMetadataAggregate.files
reportLocation = layout.buildDirectory.file("checkAggregatedSpringConfigurationMetadata/report.txt")
}
tasks.named("check") { dependsOn checkAggregatedSpringConfigurationMetadata }
tasks.register("documentConfigurationProperties", org.springframework.boot.build.context.properties.DocumentConfigurationProperties) {
configurationPropertyMetadata = configurationPropertiesMetadataAggregate.files
deprecated = false
@@ -138,7 +138,7 @@
"name": "spring.kafka.retry.topic.max-delay",
"type": "java.time.Duration",
"deprecation": {
"replacement": "spring.kafka.retry.topic.backoff.maxDelay",
"replacement": "spring.kafka.retry.topic.backoff.max-delay",
"since": "3.4.0"
}
},
@@ -14,7 +14,6 @@
"defaultValue": true,
"deprecation": {
"level": "error",
"replacement": "management.metrics.enable.process.files",
"reason": "Instead, filter 'process.files' metrics."
}
},
@@ -25,7 +24,6 @@
"defaultValue": true,
"deprecation": {
"level": "error",
"replacement": "management.metrics.enable.jvm",
"reason": "Instead, disable JvmMetricsAutoConfiguration or filter 'jvm' metrics."
}
},
@@ -36,7 +34,6 @@
"defaultValue": true,
"deprecation": {
"level": "error",
"replacement": "management.metrics.enable.logback",
"reason": "Instead, disable LogbackMetricsAutoConfiguration or filter 'logback' metrics."
}
},
@@ -366,7 +363,7 @@
"type": "java.lang.String",
"deprecation": {
"level": "error",
"replacement": "management.dynatrace.metrics.export.device-id"
"replacement": "management.dynatrace.metrics.export.v1.device-id"
}
},
{
@@ -382,7 +379,7 @@
"type": "java.lang.String",
"deprecation": {
"level": "error",
"replacement": "management.dynatrace.metrics.export.group"
"replacement": "management.dynatrace.metrics.export.v1.group"
}
},
{
@@ -413,7 +410,7 @@
"type": "java.lang.String",
"deprecation": {
"level": "error",
"replacement": "management.dynatrace.metrics.export.technology-type"
"replacement": "management.dynatrace.metrics.export.v1.technology-type"
}
},
{
@@ -1189,7 +1186,7 @@
"type": "io.micrometer.prometheus.HistogramFlavor",
"deprecation": {
"level": "error",
"replacement": "management.prometheus.metrics.export.histogram-flavor"
"reason": "No longer supported by the Prometheus client."
}
},
{
@@ -1197,7 +1194,7 @@
"type": "java.lang.String",
"deprecation": {
"level": "error",
"replacement": "management.prometheus.metrics.export.pushgateway.base-url"
"replacement": "management.prometheus.metrics.export.pushgateway.address"
}
},
{
@@ -1269,7 +1266,7 @@
"type": "java.lang.String",
"deprecation": {
"level": "error",
"replacement": "management.signalfx.metrics.export.access-token"
"reason": "SignalFX is no longer supported."
}
},
{
@@ -1277,7 +1274,7 @@
"type": "java.lang.Integer",
"deprecation": {
"level": "error",
"replacement": "management.signalfx.metrics.export.batch-size"
"reason": "SignalFX is no longer supported."
}
},
{
@@ -1285,7 +1282,7 @@
"type": "java.time.Duration",
"deprecation": {
"level": "error",
"replacement": "management.signalfx.metrics.export.connect-timeout"
"reason": "SignalFX is no longer supported."
}
},
{
@@ -1293,21 +1290,22 @@
"type": "java.lang.Boolean",
"deprecation": {
"level": "error",
"replacement": "management.signalfx.metrics.export.enabled"
"reason": "SignalFX is no longer supported."
}
},
{
"name": "management.metrics.export.signalfx.num-threads",
"type": "java.lang.Integer",
"deprecation": {
"level": "error"
"level": "error",
"reason": "SignalFX is no longer supported."
}
},
{
"name": "management.metrics.export.signalfx.published-histogram-type",
"deprecation": {
"level": "error",
"replacement": "management.signalfx.metrics.export.published-histogram-type"
"reason": "SignalFX is no longer supported."
}
},
{
@@ -1315,7 +1313,7 @@
"type": "java.time.Duration",
"deprecation": {
"level": "error",
"replacement": "management.signalfx.metrics.export.read-timeout"
"reason": "SignalFX is no longer supported."
}
},
{
@@ -1323,7 +1321,7 @@
"type": "java.lang.String",
"deprecation": {
"level": "error",
"replacement": "management.signalfx.metrics.export.source"
"reason": "SignalFX is no longer supported."
}
},
{
@@ -1331,7 +1329,7 @@
"type": "java.time.Duration",
"deprecation": {
"level": "error",
"replacement": "management.signalfx.metrics.export.step"
"reason": "SignalFX is no longer supported."
}
},
{
@@ -1339,7 +1337,7 @@
"type": "java.lang.String",
"deprecation": {
"level": "error",
"replacement": "management.signalfx.metrics.export.uri"
"reason": "SignalFX is no longer supported."
}
},
{
@@ -4,19 +4,10 @@
{
"name": "management.logging.export.otlp.enabled",
"type": "java.lang.Boolean",
"defaultValue": true,
"defaultValue": true,
"description": "Whether auto-configuration of logging is enabled to export logs over OTLP."
},
{
"name": "management.otlp.logging",
"type": "org.springframework.boot.opentelemetry.actuate.autoconfigure.logging.OpenTelemetryLoggingExportProperties",
"sourceType": "org.springframework.boot.opentelemetry.actuate.autoconfigure.logging.OpenTelemetryLoggingExportProperties",
"deprecation": {
"replacement": "management.opentelemetry.logging.export.otlp",
"level": "error"
}
},
{
{
"name": "management.otlp.logging.compression",
"type": "org.springframework.boot.opentelemetry.actuate.autoconfigure.logging.OpenTelemetryLoggingExportProperties$Compression",
"description": "Method used to compress the payload.",
@@ -48,7 +39,7 @@
"level": "error"
}
},
{
{
"name": "management.otlp.logging.export.enabled",
"deprecation": {
"replacement": "management.logging.export.otlp.enabled",