PayloadMethodArgumentResolver supports Optional

Closes gh-28945
This commit is contained in:
rstoyanchev
2023-02-13 16:58:12 +00:00
parent 5b79a57f14
commit ccbb4bdd27
2 changed files with 51 additions and 15 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
package org.springframework.messaging.handler.annotation.support;
import java.lang.annotation.Annotation;
import java.util.Optional;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotationUtils;
@@ -27,6 +28,7 @@ import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.converter.SmartMessageConverter;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
@@ -113,24 +115,30 @@ public class PayloadMethodArgumentResolver implements HandlerMethodArgumentResol
throw new IllegalStateException("@Payload SpEL expressions not supported by this resolver");
}
boolean isOptionalTargetClass = (parameter.getParameterType() == Optional.class);
Object payload = message.getPayload();
if (isEmptyPayload(payload)) {
if (ann == null || ann.required()) {
if ((ann == null || ann.required()) && !isOptionalTargetClass) {
String paramName = getParameterName(parameter);
BindingResult bindingResult = new BeanPropertyBindingResult(payload, paramName);
bindingResult.addError(new ObjectError(paramName, "Payload value must not be empty"));
throw new MethodArgumentNotValidException(message, parameter, bindingResult);
}
else {
return null;
return (isOptionalTargetClass ? Optional.empty() : null);
}
}
if (payload instanceof Optional<?> optional) {
payload = optional.get();
message = MessageBuilder.createMessage(payload, message.getHeaders());
}
Class<?> targetClass = resolveTargetClass(parameter, message);
Class<?> payloadClass = payload.getClass();
if (ClassUtils.isAssignable(targetClass, payloadClass)) {
validate(message, parameter, payload);
return payload;
return (isOptionalTargetClass ? Optional.of(payload) : payload);
}
else {
if (this.converter instanceof SmartMessageConverter smartConverter) {
@@ -144,7 +152,7 @@ public class PayloadMethodArgumentResolver implements HandlerMethodArgumentResol
payloadClass.getName() + "] to [" + targetClass.getName() + "] for " + message);
}
validate(message, parameter, payload);
return payload;
return (isOptionalTargetClass ? Optional.of(payload) : payload);
}
}
@@ -161,11 +169,14 @@ public class PayloadMethodArgumentResolver implements HandlerMethodArgumentResol
if (payload == null) {
return true;
}
else if (payload instanceof byte[]) {
return ((byte[]) payload).length == 0;
else if (payload instanceof byte[] bytes) {
return bytes.length == 0;
}
else if (payload instanceof String) {
return !StringUtils.hasText((String) payload);
else if (payload instanceof String s) {
return !StringUtils.hasText(s);
}
else if (payload instanceof Optional<?> optional) {
return optional.isEmpty();
}
else {
return false;
@@ -184,7 +195,7 @@ public class PayloadMethodArgumentResolver implements HandlerMethodArgumentResol
* @since 5.2
*/
protected Class<?> resolveTargetClass(MethodParameter parameter, Message<?> message) {
return parameter.getParameterType();
return parameter.nestedIfOptional().getNestedParameterType();
}
/**