From 2e8428b760f721544017d99ae0a0b7e3827589b3 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Tue, 9 Sep 2025 12:02:19 +0200 Subject: [PATCH] Remove NullAway suppressions where possible See gh-46926 --- .../tasks/buildinfo/BuildInfoProperties.java | 4 +-- .../springframework/boot/maven/StartMojo.java | 4 +-- .../boot/DefaultBootstrapContext.java | 4 +-- .../boot/context/properties/bind/Binder.java | 10 +++--- ...usiveConfigurationPropertiesException.java | 4 +-- .../springframework/boot/util/LambdaSafe.java | 33 +++++++++---------- .../ClientHttpRequestFactories.java | 1 - .../jdbc/metrics/DataSourcePoolMetrics.java | 1 - .../autoconfigure/PropertiesMeterFilter.java | 8 ++--- .../autoconfigure/R2dbcAutoConfiguration.java | 16 ++++----- 10 files changed, 39 insertions(+), 46 deletions(-) diff --git a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoProperties.java b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoProperties.java index 1b7e8ec6021..4029f248f0d 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoProperties.java +++ b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoProperties.java @@ -142,9 +142,9 @@ public abstract class BuildInfoProperties implements Serializable { return coerceToStringValues(applyExclusions(getAdditional().getOrElse(Collections.emptyMap()))); } - @SuppressWarnings("NullAway") // Doesn't detect lambda with correct nullability private @Nullable T getIfNotExcluded(Property property, String name) { - return getIfNotExcluded(property, name, () -> null); + Supplier<@Nullable T> supplier = () -> null; + return getIfNotExcluded(property, name, supplier); } private @Nullable T getIfNotExcluded(Property property, String name, Supplier<@Nullable T> defaultValue) { diff --git a/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java index 0a1c2647115..4a9c98f4dac 100644 --- a/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java +++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java @@ -156,12 +156,12 @@ public class StartMojo extends AbstractRunMojo { } } - @SuppressWarnings("NullAway") // Lambda isn't detected with the correct nullability private void doWaitForSpringApplication(MBeanServerConnection connection) throws MojoExecutionException, MojoFailureException { final SpringApplicationAdminClient client = new SpringApplicationAdminClient(connection, this.jmxName); try { - execute(this.wait, this.maxAttempts, () -> (client.isReady() ? true : null)); + Callable<@Nullable Boolean> isReady = () -> (client.isReady() ? true : null); + execute(this.wait, this.maxAttempts, isReady); } catch (ReflectionException ex) { throw new MojoExecutionException("Unable to retrieve 'ready' attribute", ex.getCause()); diff --git a/core/spring-boot/src/main/java/org/springframework/boot/DefaultBootstrapContext.java b/core/spring-boot/src/main/java/org/springframework/boot/DefaultBootstrapContext.java index 063aff688b4..55781f77dd3 100644 --- a/core/spring-boot/src/main/java/org/springframework/boot/DefaultBootstrapContext.java +++ b/core/spring-boot/src/main/java/org/springframework/boot/DefaultBootstrapContext.java @@ -91,9 +91,9 @@ public class DefaultBootstrapContext implements ConfigurableBootstrapContext { } @Override - @SuppressWarnings("NullAway") // Doesn't detect lambda with correct nullability public @Nullable T getOrElse(Class type, @Nullable T other) { - return getOrElseSupply(type, () -> other); + Supplier<@Nullable T> supplier = () -> other; + return getOrElseSupply(type, supplier); } @Override diff --git a/core/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/Binder.java b/core/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/Binder.java index 885d4788530..ac0298e1c9a 100644 --- a/core/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/Binder.java +++ b/core/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/Binder.java @@ -459,7 +459,6 @@ public class Binder { return null; } - @SuppressWarnings("NullAway") // Doesn't detect lambda with correct nullability private @Nullable Object bindAggregate(ConfigurationPropertyName name, Bindable target, BindHandler handler, Context context, AggregateBinder aggregateBinder) { AggregateElementBinder elementBinder = (itemName, itemTarget, source) -> { @@ -467,7 +466,8 @@ public class Binder { Supplier supplier = () -> bind(itemName, itemTarget, handler, context, allowRecursiveBinding, false); return context.withSource(source, supplier); }; - return context.withIncreasedDepth(() -> aggregateBinder.bind(name, target, elementBinder)); + Supplier<@Nullable Object> supplier = () -> aggregateBinder.bind(name, target, elementBinder); + return context.withIncreasedDepth(supplier); } private @Nullable ConfigurationProperty findProperty(ConfigurationPropertyName name, Bindable target, @@ -492,7 +492,6 @@ public class Binder { return result; } - @SuppressWarnings("NullAway") // Doesn't detect lambda with correct nullability private @Nullable Object bindDataObject(ConfigurationPropertyName name, Bindable target, BindHandler handler, Context context, boolean allowRecursiveBinding) { if (isUnbindableBean(name, target, context)) { @@ -505,8 +504,9 @@ public class Binder { } DataObjectPropertyBinder propertyBinder = (propertyName, propertyTarget) -> bind(name.append(propertyName), propertyTarget, handler, context, false, false); - return context.withDataObject(type, () -> fromDataObjectBinders(bindMethod, - (dataObjectBinder) -> dataObjectBinder.bind(name, target, context, propertyBinder))); + Supplier<@Nullable Object> supplier = () -> fromDataObjectBinders(bindMethod, + (dataObjectBinder) -> dataObjectBinder.bind(name, target, context, propertyBinder)); + return context.withDataObject(type, supplier); } private @Nullable Object fromDataObjectBinders(@Nullable BindMethod bindMethod, diff --git a/core/spring-boot/src/main/java/org/springframework/boot/context/properties/source/MutuallyExclusiveConfigurationPropertiesException.java b/core/spring-boot/src/main/java/org/springframework/boot/context/properties/source/MutuallyExclusiveConfigurationPropertiesException.java index a9354c0d782..95379add440 100644 --- a/core/spring-boot/src/main/java/org/springframework/boot/context/properties/source/MutuallyExclusiveConfigurationPropertiesException.java +++ b/core/spring-boot/src/main/java/org/springframework/boot/context/properties/source/MutuallyExclusiveConfigurationPropertiesException.java @@ -101,9 +101,9 @@ public class MutuallyExclusiveConfigurationPropertiesException extends RuntimeEx * non-null values are defined in a set of entries. * @param entries a consumer used to populate the entries to check */ - @SuppressWarnings("NullAway") // Doesn't detect lambda with correct nullability public static void throwIfMultipleNonNullValuesIn(Consumer> entries) { - throwIfMultipleMatchingValuesIn(entries, Objects::nonNull); + Predicate<@Nullable Object> isNonNull = Objects::nonNull; + throwIfMultipleMatchingValuesIn(entries, isNonNull); } /** diff --git a/core/spring-boot/src/main/java/org/springframework/boot/util/LambdaSafe.java b/core/spring-boot/src/main/java/org/springframework/boot/util/LambdaSafe.java index 5542f295dd5..351c11b9122 100644 --- a/core/spring-boot/src/main/java/org/springframework/boot/util/LambdaSafe.java +++ b/core/spring-boot/src/main/java/org/springframework/boot/util/LambdaSafe.java @@ -252,13 +252,12 @@ public final class LambdaSafe { * Invoke the callback instance where the callback method returns void. * @param invoker the invoker used to invoke the callback */ - // Lambda isn't detected with the correct nullability - @SuppressWarnings("NullAway") public void invoke(Consumer invoker) { - invoke(this.callbackInstance, () -> { + Supplier<@Nullable Void> supplier = () -> { invoker.accept(this.callbackInstance); return null; - }); + }; + invoke(this.callbackInstance, supplier); } /** @@ -268,10 +267,9 @@ public final class LambdaSafe { * @return the result of the invocation (may be {@link InvocationResult#noResult} * if the callback was not invoked) */ - // Lambda isn't detected with the correct nullability - @SuppressWarnings("NullAway") public InvocationResult invokeAnd(Function invoker) { - return invoke(this.callbackInstance, () -> invoker.apply(this.callbackInstance)); + Supplier<@Nullable R> supplier = () -> invoker.apply(this.callbackInstance); + return invoke(this.callbackInstance, supplier); } } @@ -296,13 +294,14 @@ public final class LambdaSafe { * Invoke the callback instances where the callback method returns void. * @param invoker the invoker used to invoke the callback */ - // Lambda isn't detected with the correct nullability - @SuppressWarnings("NullAway") public void invoke(Consumer invoker) { - this.callbackInstances.forEach((callbackInstance) -> invoke(callbackInstance, () -> { - invoker.accept(callbackInstance); - return null; - })); + this.callbackInstances.forEach((callbackInstance) -> { + Supplier<@Nullable Void> supplier = () -> { + invoker.accept(callbackInstance); + return null; + }; + invoke(callbackInstance, supplier); + }); } /** @@ -312,11 +311,11 @@ public final class LambdaSafe { * @return the results of the invocation (may be an empty stream if no callbacks * could be called) */ - // Lambda isn't detected with the correct nullability - @SuppressWarnings("NullAway") public Stream invokeAnd(Function invoker) { - Function> mapper = (callbackInstance) -> invoke(callbackInstance, - () -> invoker.apply(callbackInstance)); + Function> mapper = (callbackInstance) -> { + Supplier<@Nullable R> supplier = () -> invoker.apply(callbackInstance); + return invoke(callbackInstance, supplier); + }; return this.callbackInstances.stream() .map(mapper) .filter(InvocationResult::hasResult) diff --git a/module/spring-boot-http-client/src/main/java/org/springframework/boot/http/client/autoconfigure/ClientHttpRequestFactories.java b/module/spring-boot-http-client/src/main/java/org/springframework/boot/http/client/autoconfigure/ClientHttpRequestFactories.java index dedfe04f344..c6541b90927 100644 --- a/module/spring-boot-http-client/src/main/java/org/springframework/boot/http/client/autoconfigure/ClientHttpRequestFactories.java +++ b/module/spring-boot-http-client/src/main/java/org/springframework/boot/http/client/autoconfigure/ClientHttpRequestFactories.java @@ -100,7 +100,6 @@ public final class ClientHttpRequestFactories { return getProperty(accessor, Function.identity(), predicate, fallback, fallbackAccessor); } - @SuppressWarnings("NullAway") // Lambda isn't detected with the correct nullability private @Nullable T getProperty(Function accessor, Function extractor, Predicate<@Nullable T> predicate, @Nullable F fallback, Function fallbackAccessor) { diff --git a/module/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/metrics/DataSourcePoolMetrics.java b/module/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/metrics/DataSourcePoolMetrics.java index 18d5267e066..e9ee62d9176 100644 --- a/module/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/metrics/DataSourcePoolMetrics.java +++ b/module/spring-boot-jdbc/src/main/java/org/springframework/boot/jdbc/metrics/DataSourcePoolMetrics.java @@ -81,7 +81,6 @@ public class DataSourcePoolMetrics implements MeterBinder { } } - @SuppressWarnings("NullAway") // Lambda isn't detected with the correct nullability private void bindPoolMetadata(MeterRegistry registry, String metricName, String description, Function function) { bindDataSource(registry, metricName, description, this.metadataProvider.getValueFunction(function)); diff --git a/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/PropertiesMeterFilter.java b/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/PropertiesMeterFilter.java index 77b6a009053..e1ce6d79d20 100644 --- a/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/PropertiesMeterFilter.java +++ b/module/spring-boot-micrometer-metrics/src/main/java/org/springframework/boot/micrometer/metrics/autoconfigure/PropertiesMeterFilter.java @@ -117,21 +117,21 @@ public class PropertiesMeterFilter implements MeterFilter { return (value != null) ? MeterValue.valueOf(value).getValue(meterType) : null; } - @SuppressWarnings("NullAway") // Lambda isn't detected with the correct nullability private @Nullable T lookup(Map values, Id id, @Nullable T defaultValue) { if (values.isEmpty()) { return defaultValue; } - return doLookup(values, id, () -> defaultValue); + Supplier<@Nullable T> getDefaultValue = () -> defaultValue; + return doLookup(values, id, getDefaultValue); } @Contract("_, _, !null -> !null") - @SuppressWarnings("NullAway") // Lambda isn't detected with the correct nullability private @Nullable T lookupWithFallbackToAll(Map values, Id id, @Nullable T defaultValue) { if (values.isEmpty()) { return defaultValue; } - return doLookup(values, id, () -> values.getOrDefault("all", defaultValue)); + Supplier<@Nullable T> getAllOrDefaultValue = () -> values.getOrDefault("all", defaultValue); + return doLookup(values, id, getAllOrDefaultValue); } private @Nullable T doLookup(Map values, Id id, Supplier<@Nullable T> defaultValue) { diff --git a/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/autoconfigure/R2dbcAutoConfiguration.java b/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/autoconfigure/R2dbcAutoConfiguration.java index 7ffb70e70d7..486d6a43c40 100644 --- a/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/autoconfigure/R2dbcAutoConfiguration.java +++ b/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/autoconfigure/R2dbcAutoConfiguration.java @@ -83,23 +83,19 @@ public final class R2dbcAutoConfiguration { return optionsBuilder.build(); } - // Lambda isn't detected with the correct nullability - @SuppressWarnings("NullAway") private void configureDatabase(Builder optionsBuilder, ConnectionFactoryOptions urlOptions) { - configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.DATABASE, - () -> determineDatabaseName(this.properties)); + Supplier<@Nullable String> getDatabaseName = () -> determineDatabaseName(this.properties); + configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.DATABASE, getDatabaseName); } - // Lambda isn't detected with the correct nullability - @SuppressWarnings("NullAway") private void configurePassword(Builder optionsBuilder, ConnectionFactoryOptions urlOptions) { - configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.PASSWORD, this.properties::getPassword); + Supplier<@Nullable CharSequence> getPassword = this.properties::getPassword; + configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.PASSWORD, getPassword); } - // Lambda isn't detected with the correct nullability - @SuppressWarnings("NullAway") private void configureUser(Builder optionsBuilder, ConnectionFactoryOptions urlOptions) { - configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.USER, this.properties::getUsername); + Supplier<@Nullable String> getUsername = this.properties::getUsername; + configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.USER, getUsername); } private void configureIf(Builder optionsBuilder,