From 3207f57e95bb2108a7db638156f7fca2e917a69e Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Mon, 4 Aug 2025 13:38:15 +0200 Subject: [PATCH] Add nullability annotations to module/spring-boot-observation See gh-46587 --- .../autoconfigure/ObservationHandlerGroups.java | 13 ++++++++++--- .../ObservationRegistryPostProcessor.java | 3 ++- .../autoconfigure/SpelValueExpressionResolver.java | 8 ++++++-- .../observation/autoconfigure/package-info.java | 3 +++ 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/ObservationHandlerGroups.java b/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/ObservationHandlerGroups.java index 5bf93b999d5..f153819f85a 100644 --- a/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/ObservationHandlerGroups.java +++ b/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/ObservationHandlerGroups.java @@ -23,6 +23,7 @@ import java.util.List; import io.micrometer.observation.ObservationHandler; import io.micrometer.observation.ObservationRegistry.ObservationConfig; +import org.jspecify.annotations.Nullable; import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; @@ -52,8 +53,15 @@ class ObservationHandlerGroups { void register(ObservationConfig config, List> handlers) { MultiValueMap> grouped = new LinkedMultiValueMap<>(); + List> unclaimed = new ArrayList<>(); for (ObservationHandler handler : handlers) { - grouped.add(findGroup(handler), handler); + ObservationHandlerGroup group = findGroup(handler); + if (group == null) { + unclaimed.add(handler); + } + else { + grouped.add(group, handler); + } } for (ObservationHandlerGroup group : this.groups) { List> members = grouped.get(group); @@ -61,7 +69,6 @@ class ObservationHandlerGroups { group.registerMembers(config, members); } } - List> unclaimed = grouped.get(null); if (!CollectionUtils.isEmpty(unclaimed)) { for (ObservationHandler handler : unclaimed) { config.observationHandler(handler); @@ -69,7 +76,7 @@ class ObservationHandlerGroups { } } - private ObservationHandlerGroup findGroup(ObservationHandler handler) { + private @Nullable ObservationHandlerGroup findGroup(ObservationHandler handler) { for (ObservationHandlerGroup group : this.groups) { if (group.isMember(handler)) { return group; diff --git a/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/ObservationRegistryPostProcessor.java b/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/ObservationRegistryPostProcessor.java index 4c10d172093..b9a0fa36448 100644 --- a/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/ObservationRegistryPostProcessor.java +++ b/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/ObservationRegistryPostProcessor.java @@ -21,6 +21,7 @@ import io.micrometer.observation.ObservationFilter; import io.micrometer.observation.ObservationHandler; import io.micrometer.observation.ObservationPredicate; import io.micrometer.observation.ObservationRegistry; +import org.jspecify.annotations.Nullable; import org.springframework.beans.BeansException; import org.springframework.beans.factory.ObjectProvider; @@ -47,7 +48,7 @@ class ObservationRegistryPostProcessor implements BeanPostProcessor { private final ObjectProvider observationFilters; - private volatile ObservationRegistryConfigurer configurer; + private volatile @Nullable ObservationRegistryConfigurer configurer; ObservationRegistryPostProcessor(ObjectProvider> observationRegistryCustomizers, ObjectProvider observationPredicates, diff --git a/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/SpelValueExpressionResolver.java b/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/SpelValueExpressionResolver.java index a31aa038766..10c03a148b8 100644 --- a/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/SpelValueExpressionResolver.java +++ b/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/SpelValueExpressionResolver.java @@ -17,11 +17,13 @@ package org.springframework.boot.observation.autoconfigure; import io.micrometer.common.annotation.ValueExpressionResolver; +import org.jspecify.annotations.Nullable; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.SimpleEvaluationContext; +import org.springframework.util.Assert; /** * A {@link Expression SpEL}-based {@link ValueExpressionResolver}. @@ -33,11 +35,13 @@ class SpelValueExpressionResolver implements ValueExpressionResolver { private final ExpressionParser expressionParser = new SpelExpressionParser(); @Override - public String resolve(String expression, Object parameter) { + public String resolve(String expression, @Nullable Object parameter) { try { SimpleEvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build(); Expression expressionToEvaluate = this.expressionParser.parseExpression(expression); - return expressionToEvaluate.getValue(context, parameter, String.class); + String value = expressionToEvaluate.getValue(context, parameter, String.class); + Assert.state(value != null, "'value' must not be null"); + return value; } catch (Exception ex) { throw new IllegalStateException("Unable to evaluate SpEL expression '%s'".formatted(expression), ex); diff --git a/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/package-info.java b/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/package-info.java index bd061e75fd0..410821ad523 100644 --- a/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/package-info.java +++ b/module/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/package-info.java @@ -17,4 +17,7 @@ /** * Auto-configuration for Micrometer Observation. */ +@NullMarked package org.springframework.boot.observation.autoconfigure; + +import org.jspecify.annotations.NullMarked;