From abccba22f1511efd6d5e8cb5b00f16ba15b83e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Thu, 26 Dec 2024 16:00:24 +0100 Subject: [PATCH] Refine null-safety in the spring-messaging module Closes gh-34158 --- .../handler/invocation/AbstractMethodMessageHandler.java | 5 +++-- .../invocation/reactive/AbstractMethodMessageHandler.java | 5 +++-- .../messaging/rsocket/service/RSocketServiceMethod.java | 2 +- .../springframework/messaging/simp/stomp/StompDecoder.java | 2 +- .../messaging/simp/stomp/StompHeaderAccessor.java | 2 +- .../springframework/messaging/simp/stomp/StompHeaders.java | 2 +- .../handler/invocation/MethodMessageHandlerTests.java | 3 ++- 7 files changed, 12 insertions(+), 9 deletions(-) diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java index 99279d4827c..ee92516c487 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java @@ -514,12 +514,13 @@ public abstract class AbstractMethodMessageHandler handleMatch(bestMatch.mapping, bestMatch.handlerMethod, lookupDestination, message); } - @SuppressWarnings("NullAway") private void addMatchesToCollection(Collection mappingsToCheck, Message message, List matches) { for (T mapping : mappingsToCheck) { T match = getMatchingMapping(mapping, message); if (match != null) { - matches.add(new Match(match, this.handlerMethods.get(mapping))); + HandlerMethod handlerMethod = this.handlerMethods.get(mapping); + Assert.state(handlerMethod != null, "HandlerMethod must not be null"); + matches.add(new Match(match, handlerMethod)); } } } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java index 145a1b214a1..df813633e69 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java @@ -496,14 +496,15 @@ public abstract class AbstractMethodMessageHandler */ protected abstract RouteMatcher.@Nullable Route getDestination(Message message); - @SuppressWarnings("NullAway") private void addMatchesToCollection( Collection mappingsToCheck, Message message, List> matches) { for (T mapping : mappingsToCheck) { T match = getMatchingMapping(mapping, message); if (match != null) { - matches.add(new Match<>(match, this.handlerMethods.get(mapping))); + HandlerMethod handlerMethod = this.handlerMethods.get(mapping); + Assert.state(handlerMethod != null, "HandlerMethod must not be null"); + matches.add(new Match<>(match, handlerMethod)); } } } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceMethod.java b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceMethod.java index acc60e3cb7d..8c16336e495 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceMethod.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceMethod.java @@ -90,7 +90,7 @@ final class RSocketServiceMethod { return parameters; } - @SuppressWarnings("NullAway") + @SuppressWarnings("NullAway") // Dataflow analysis limitation private static @Nullable String initRoute( Method method, Class containingClass, RSocketStrategies strategies, @Nullable StringValueResolver embeddedValueResolver) { diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java index f3a2c800576..3e36da4a73e 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java @@ -127,7 +127,7 @@ public class StompDecoder { /** * Decode a single STOMP frame from the given {@code byteBuffer} into a {@link Message}. */ - @SuppressWarnings("NullAway") + @SuppressWarnings("NullAway") // Dataflow analysis limitation private @Nullable Message decodeMessage(ByteBuffer byteBuffer, @Nullable MultiValueMap headers) { Message decodedMessage = null; skipEol(byteBuffer); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java index 6320d9f3a31..03cc9b1fe61 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java @@ -236,7 +236,7 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { return (SimpMessageType.HEARTBEAT == getMessageType()); } - @SuppressWarnings("NullAway") + @SuppressWarnings("NullAway") // Dataflow analysis limitation public long[] getHeartbeat() { String rawValue = getFirstNativeHeader(STOMP_HEARTBEAT_HEADER); int pos = (rawValue != null ? rawValue.indexOf(',') : -1); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaders.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaders.java index f023946fb1c..e39a580293c 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaders.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaders.java @@ -272,7 +272,7 @@ public class StompHeaders implements MultiValueMap, Serializable /** * Get the heartbeat header. */ - @SuppressWarnings("NullAway") + @SuppressWarnings("NullAway") // Dataflow analysis limitation public long @Nullable [] getHeartbeat() { String rawValue = getFirst(HEARTBEAT); int pos = (rawValue != null ? rawValue.indexOf(',') : -1); diff --git a/spring-messaging/src/test/java/org/springframework/messaging/handler/invocation/MethodMessageHandlerTests.java b/spring-messaging/src/test/java/org/springframework/messaging/handler/invocation/MethodMessageHandlerTests.java index 5fb96aaa9c4..45013cc4f57 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/handler/invocation/MethodMessageHandlerTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/handler/invocation/MethodMessageHandlerTests.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -236,7 +237,7 @@ class MethodMessageHandlerTests { } @Override - protected String getMatchingMapping(String mapping, Message message) { + protected @Nullable String getMatchingMapping(String mapping, Message message) { String destination = getLookupDestination(getDestination(message)); Assert.notNull(destination, "No destination"); return mapping.equals(destination) || this.pathMatcher.match(mapping, destination) ? mapping : null;