From 4ad5d26cdaa5499b55d4afb2d98de52804d30da2 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Tue, 22 Jul 2025 14:02:21 +0200 Subject: [PATCH] Add nullability annotations to core/spring-boot-properties-migrator See gh-46587 --- .../migrator/PropertiesMigrationListener.java | 3 ++- .../migrator/PropertiesMigrationReport.java | 6 ++++-- .../migrator/PropertiesMigrationReporter.java | 16 ++++++++++----- .../migrator/PropertyMigration.java | 20 +++++++++++-------- .../properties/migrator/package-info.java | 3 +++ 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationListener.java b/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationListener.java index af0c4785df8..1522b25debd 100644 --- a/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationListener.java +++ b/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationListener.java @@ -21,6 +21,7 @@ import java.io.InputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.boot.configurationmetadata.ConfigurationMetadataRepository; import org.springframework.boot.configurationmetadata.ConfigurationMetadataRepositoryJsonBuilder; @@ -44,7 +45,7 @@ class PropertiesMigrationListener implements ApplicationListener> content = getContent(LegacyProperties::getRenamed); if (content.isEmpty()) { return null; @@ -60,7 +62,7 @@ class PropertiesMigrationReport { * properties were found, return {@code null}. * @return a report with the configurations keys that are no longer supported */ - String getErrorReport() { + @Nullable String getErrorReport() { Map> content = getContent(LegacyProperties::getUnsupported); if (content.isEmpty()) { return null; diff --git a/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationReporter.java b/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationReporter.java index 2712552dbe5..8a9e5dc2406 100644 --- a/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationReporter.java +++ b/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationReporter.java @@ -26,6 +26,8 @@ import java.util.Objects; import java.util.Set; import java.util.function.Predicate; +import org.jspecify.annotations.Nullable; + import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty; import org.springframework.boot.configurationmetadata.ConfigurationMetadataRepository; import org.springframework.boot.context.properties.source.ConfigurationProperty; @@ -38,6 +40,7 @@ import org.springframework.boot.origin.OriginTrackedValue; import org.springframework.boot.origin.PropertySourceOrigin; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.PropertySource; +import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; @@ -109,7 +112,9 @@ class PropertiesMigrationReporter { if (source.getUnderlyingSource() instanceof PropertySource underlyingSource) { return underlyingSource.getName(); } - return source.getUnderlyingSource().toString(); + Object underlyingSource = source.getUnderlyingSource(); + Assert.state(underlyingSource != null, "'underlyingSource' must not be null"); + return underlyingSource.toString(); } private List getMigrations(ConfigurationPropertySource propertySource, @@ -149,7 +154,8 @@ class PropertiesMigrationReporter { && Objects.equals(propertySourceOrigin.getPropertyName(), replacement.getId()); } - private ConfigurationMetadataProperty determineReplacementMetadata(ConfigurationMetadataProperty metadata) { + private @Nullable ConfigurationMetadataProperty determineReplacementMetadata( + ConfigurationMetadataProperty metadata) { String replacementId = metadata.getDeprecation().getReplacement(); if (StringUtils.hasText(replacementId)) { ConfigurationMetadataProperty replacement = this.allProperties.get(replacementId); @@ -161,7 +167,7 @@ class PropertiesMigrationReporter { return null; } - private ConfigurationMetadataProperty detectMapValueReplacement(String fullId) { + private @Nullable ConfigurationMetadataProperty detectMapValueReplacement(String fullId) { int lastDot = fullId.lastIndexOf('.'); if (lastDot == -1) { return null; @@ -178,7 +184,7 @@ class PropertiesMigrationReporter { return type != null && type.startsWith(Map.class.getName()); } - private PropertySource mapPropertiesWithReplacement(PropertiesMigrationReport report, String name, + private @Nullable PropertySource mapPropertiesWithReplacement(PropertiesMigrationReport report, String name, List properties) { report.add(name, properties); List renamed = properties.stream().filter(PropertyMigration::isCompatibleType).toList(); @@ -229,7 +235,7 @@ class PropertiesMigrationReporter { } @Override - public Object getProperty(String name) { + public @Nullable Object getProperty(String name) { this.accessedNames.add(name); return null; } diff --git a/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertyMigration.java b/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertyMigration.java index a442d06493a..48b714b4c2c 100644 --- a/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertyMigration.java +++ b/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertyMigration.java @@ -20,6 +20,8 @@ import java.time.Duration; import java.util.Comparator; import java.util.Map; +import org.jspecify.annotations.Nullable; + import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty; import org.springframework.boot.configurationmetadata.Deprecation; import org.springframework.boot.context.properties.source.ConfigurationProperty; @@ -43,11 +45,11 @@ class PropertyMigration { private final ConfigurationProperty property; - private final Integer lineNumber; + private final @Nullable Integer lineNumber; private final ConfigurationMetadataProperty metadata; - private final ConfigurationMetadataProperty replacementMetadata; + private final @Nullable ConfigurationMetadataProperty replacementMetadata; /** * Whether this migration happened from a map type. @@ -57,7 +59,7 @@ class PropertyMigration { private final boolean compatibleType; PropertyMigration(ConfigurationProperty property, ConfigurationMetadataProperty metadata, - ConfigurationMetadataProperty replacementMetadata, boolean mapMigration) { + @Nullable ConfigurationMetadataProperty replacementMetadata, boolean mapMigration) { this.property = property; this.lineNumber = determineLineNumber(property); this.metadata = metadata; @@ -66,7 +68,7 @@ class PropertyMigration { this.compatibleType = determineCompatibleType(metadata, replacementMetadata); } - private static Integer determineLineNumber(ConfigurationProperty property) { + private static @Nullable Integer determineLineNumber(ConfigurationProperty property) { Origin origin = property.getOrigin(); if (origin instanceof PropertySourceOrigin propertySourceOrigin) { origin = propertySourceOrigin.getOrigin(); @@ -80,7 +82,7 @@ class PropertyMigration { } private static boolean determineCompatibleType(ConfigurationMetadataProperty metadata, - ConfigurationMetadataProperty replacementMetadata) { + @Nullable ConfigurationMetadataProperty replacementMetadata) { String currentType = determineType(metadata); String replacementType = determineType(replacementMetadata); if (currentType == null || replacementType == null) { @@ -93,7 +95,7 @@ class PropertyMigration { && (currentType.equals(Long.class.getName()) || currentType.equals(Integer.class.getName())); } - private static String determineType(ConfigurationMetadataProperty metadata) { + private static @Nullable String determineType(@Nullable ConfigurationMetadataProperty metadata) { if (metadata == null || metadata.getType() == null) { return null; } @@ -112,7 +114,7 @@ class PropertyMigration { return this.property; } - Integer getLineNumber() { + @Nullable Integer getLineNumber() { return this.lineNumber; } @@ -126,7 +128,9 @@ class PropertyMigration { String getNewPropertyName() { if (this.mapMigration) { - return getNewMapPropertyName(this.property, this.metadata, this.replacementMetadata).toString(); + ConfigurationMetadataProperty replacementMetadata = this.replacementMetadata; + Assert.state(replacementMetadata != null, "'replacementMetadata' must not be null"); + return getNewMapPropertyName(this.property, this.metadata, replacementMetadata).toString(); } return this.metadata.getDeprecation().getReplacement(); } diff --git a/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/package-info.java b/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/package-info.java index 03c7c5ff69b..ecaf5ed0073 100644 --- a/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/package-info.java +++ b/core/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/package-info.java @@ -17,4 +17,7 @@ /** * Support for migrating legacy Spring Boot properties. */ +@NullMarked package org.springframework.boot.context.properties.migrator; + +import org.jspecify.annotations.NullMarked;