From dea31dd55e9859a4e7d0d5dddbb3d93799090ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Mon, 25 Mar 2024 12:24:53 +0100 Subject: [PATCH] Refine null-safety in spring-messaging See gh-32475 --- .../springframework/messaging/MessageDeliveryException.java | 6 ++++-- .../org/springframework/messaging/MessagingException.java | 2 +- .../converter/MappingJackson2MessageConverter.java | 3 ++- .../messaging/handler/CompositeMessageCondition.java | 1 + .../reactive/AbstractNamedValueMethodArgumentResolver.java | 1 + .../annotation/reactive/MessageMappingMessageHandler.java | 3 +++ .../support/AbstractNamedValueMethodArgumentResolver.java | 1 + .../handler/invocation/InvocableHandlerMethod.java | 4 ++-- .../handler/invocation/ReactiveReturnValueHandler.java | 2 ++ .../support/RSocketFrameTypeMessageCondition.java | 1 + .../rsocket/service/RSocketServiceProxyFactory.java | 1 + .../annotation/support/PrincipalMethodArgumentResolver.java | 2 ++ .../support/SimpAnnotationMethodMessageHandler.java | 1 + 13 files changed, 22 insertions(+), 6 deletions(-) diff --git a/spring-messaging/src/main/java/org/springframework/messaging/MessageDeliveryException.java b/spring-messaging/src/main/java/org/springframework/messaging/MessageDeliveryException.java index 176cdb250ecb..f73fafb8960e 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/MessageDeliveryException.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/MessageDeliveryException.java @@ -16,6 +16,8 @@ package org.springframework.messaging; +import org.springframework.lang.Nullable; + /** * Exception that indicates an error occurred during message delivery. * @@ -37,11 +39,11 @@ public MessageDeliveryException(Message undeliveredMessage, String descriptio super(undeliveredMessage, description); } - public MessageDeliveryException(Message message, Throwable cause) { + public MessageDeliveryException(Message message, @Nullable Throwable cause) { super(message, cause); } - public MessageDeliveryException(Message undeliveredMessage, String description, Throwable cause) { + public MessageDeliveryException(Message undeliveredMessage, String description, @Nullable Throwable cause) { super(undeliveredMessage, description, cause); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/MessagingException.java b/spring-messaging/src/main/java/org/springframework/messaging/MessagingException.java index d657ab7c1761..bd2f8d26af1d 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/MessagingException.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/MessagingException.java @@ -53,7 +53,7 @@ public MessagingException(Message message, String description) { this.failedMessage = message; } - public MessagingException(Message message, Throwable cause) { + public MessagingException(Message message, @Nullable Throwable cause) { super(null, cause); this.failedMessage = message; } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java b/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java index 64f31c3056f9..715f02e61e0c 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java @@ -200,7 +200,8 @@ protected void logWarningIfNecessary(Type type, @Nullable Throwable cause) { } // Do not log warning for serializer not found (note: different message wording on Jackson 2.9) - boolean debugLevel = (cause instanceof JsonMappingException && cause.getMessage().startsWith("Cannot find")); + boolean debugLevel = (cause instanceof JsonMappingException && cause.getMessage() != null + && cause.getMessage().startsWith("Cannot find")); if (debugLevel ? logger.isDebugEnabled() : logger.isWarnEnabled()) { String msg = "Failed to evaluate Jackson " + (type instanceof JavaType ? "de" : "") + diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/CompositeMessageCondition.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/CompositeMessageCondition.java index 4d4d21614b99..d9c908fb9284 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/CompositeMessageCondition.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/CompositeMessageCondition.java @@ -80,6 +80,7 @@ private > T combine(MessageCondition first, Mes } @Override + @Nullable public CompositeMessageCondition getMatchingCondition(Message message) { List> result = new ArrayList<>(this.messageConditions.size()); for (MessageCondition condition : this.messageConditions) { diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/AbstractNamedValueMethodArgumentResolver.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/AbstractNamedValueMethodArgumentResolver.java index 054a9762049e..87da70b87428 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/AbstractNamedValueMethodArgumentResolver.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/AbstractNamedValueMethodArgumentResolver.java @@ -81,6 +81,7 @@ protected AbstractNamedValueMethodArgumentResolver(ConversionService conversionS @Override + @Nullable public Object resolveArgumentValue(MethodParameter parameter, Message message) { NamedValueInfo namedValueInfo = getNamedValueInfo(parameter); MethodParameter nestedParameter = parameter.nestedIfOptional(); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java index ff44fa0a4d58..c4872d1825f0 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java @@ -272,6 +272,7 @@ protected List initReturnValueHandler @Override + @Nullable protected CompositeMessageCondition getMappingForMethod(Method method, Class handlerType) { CompositeMessageCondition methodCondition = getCondition(method); if (methodCondition != null) { @@ -325,12 +326,14 @@ protected Set getDirectLookupMappings(CompositeMessageCondition mapping) } @Override + @Nullable protected RouteMatcher.Route getDestination(Message message) { return (RouteMatcher.Route) message.getHeaders() .get(DestinationPatternsMessageCondition.LOOKUP_DESTINATION_HEADER); } @Override + @Nullable protected CompositeMessageCondition getMatchingMapping(CompositeMessageCondition mapping, Message message) { return mapping.getMatchingCondition(message); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/AbstractNamedValueMethodArgumentResolver.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/AbstractNamedValueMethodArgumentResolver.java index 8f2febc4faf0..ca6cbd427b1b 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/AbstractNamedValueMethodArgumentResolver.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/AbstractNamedValueMethodArgumentResolver.java @@ -89,6 +89,7 @@ protected AbstractNamedValueMethodArgumentResolver(ConversionService conversionS @Override + @Nullable public Object resolveArgument(MethodParameter parameter, Message message) throws Exception { NamedValueInfo namedValueInfo = getNamedValueInfo(parameter); MethodParameter nestedParameter = parameter.nestedIfOptional(); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java index 5a3720dc4e08..40d2ac4ad4a8 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java @@ -111,7 +111,7 @@ public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDisc * @see #doInvoke */ @Nullable - public Object invoke(Message message, Object... providedArgs) throws Exception { + public Object invoke(Message message, @Nullable Object... providedArgs) throws Exception { Object[] args = getMethodArgumentValues(message, providedArgs); if (logger.isTraceEnabled()) { logger.trace("Arguments: " + Arrays.toString(args)); @@ -125,7 +125,7 @@ public Object invoke(Message message, Object... providedArgs) throws Exceptio *

The resulting array will be passed into {@link #doInvoke}. * @since 5.1.2 */ - protected Object[] getMethodArgumentValues(Message message, Object... providedArgs) throws Exception { + protected Object[] getMethodArgumentValues(Message message, @Nullable Object... providedArgs) throws Exception { MethodParameter[] parameters = getMethodParameters(); if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS; diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/ReactiveReturnValueHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/ReactiveReturnValueHandler.java index f843ad250611..18a5948f64d2 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/ReactiveReturnValueHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/ReactiveReturnValueHandler.java @@ -23,6 +23,7 @@ import org.springframework.core.MethodParameter; import org.springframework.core.ReactiveAdapter; import org.springframework.core.ReactiveAdapterRegistry; +import org.springframework.lang.Nullable; /** * Support for single-value reactive types (like {@code Mono} or {@code Single}) @@ -57,6 +58,7 @@ public boolean isAsyncReturnValue(Object returnValue, MethodParameter returnType } @Override + @Nullable public CompletableFuture toCompletableFuture(Object returnValue, MethodParameter returnType) { ReactiveAdapter adapter = this.adapterRegistry.getAdapter(returnType.getParameterType(), returnValue); if (adapter != null) { diff --git a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketFrameTypeMessageCondition.java b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketFrameTypeMessageCondition.java index 7ef34875ffe1..96eea1f3c993 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketFrameTypeMessageCondition.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketFrameTypeMessageCondition.java @@ -134,6 +134,7 @@ public RSocketFrameTypeMessageCondition combine(RSocketFrameTypeMessageCondition } @Override + @Nullable public RSocketFrameTypeMessageCondition getMatchingCondition(Message message) { FrameType actual = message.getHeaders().get(FRAME_TYPE_HEADER, FrameType.class); if (actual != null) { diff --git a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceProxyFactory.java b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceProxyFactory.java index ffa2833edf03..bfab89ed5789 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceProxyFactory.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceProxyFactory.java @@ -247,6 +247,7 @@ private ServiceMethodInterceptor(List methods) { } @Override + @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { Method method = invocation.getMethod(); RSocketServiceMethod serviceMethod = this.serviceMethods.get(method); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/PrincipalMethodArgumentResolver.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/PrincipalMethodArgumentResolver.java index 6b9a01338688..524f4b973d2f 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/PrincipalMethodArgumentResolver.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/PrincipalMethodArgumentResolver.java @@ -20,6 +20,7 @@ import java.util.Optional; import org.springframework.core.MethodParameter; +import org.springframework.lang.Nullable; import org.springframework.messaging.Message; import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver; import org.springframework.messaging.simp.SimpMessageHeaderAccessor; @@ -40,6 +41,7 @@ public boolean supportsParameter(MethodParameter parameter) { } @Override + @Nullable public Object resolveArgument(MethodParameter parameter, Message message){ Principal user = SimpMessageHeaderAccessor.getUser(message.getHeaders()); return parameter.isOptional() ? Optional.ofNullable(user) : user; diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/SimpAnnotationMethodMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/SimpAnnotationMethodMessageHandler.java index 9974aa8ea52e..d7955dd4edd2 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/SimpAnnotationMethodMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/SimpAnnotationMethodMessageHandler.java @@ -476,6 +476,7 @@ protected String getDestination(Message message) { } @Override + @Nullable protected String getLookupDestination(@Nullable String destination) { if (destination == null) { return null;