Resolve property-dependent parameter names for exception messages
Prior to this commit when a required parameter defined as a property or expression placeholder was missing, the exception thrown would refer to the placeholder instead of the resolved name. This change covers messaging handlers and web controllers, both blocking and reactive. It also fixes the error message when handling null values for non-required parameters, as well as in cases that need conversion. See gh-32323 Closes gh-32462
This commit is contained in:
committed by
Simon Baslé
parent
5698191ba0
commit
458c30cb63
@@ -36,6 +36,7 @@ import org.springframework.messaging.support.NativeMessageHeaderAccessor;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.springframework.messaging.handler.annotation.MessagingPredicates.header;
|
||||
import static org.springframework.messaging.handler.annotation.MessagingPredicates.headerPlain;
|
||||
|
||||
@@ -151,6 +152,37 @@ class HeaderMethodArgumentResolverTests {
|
||||
assertThat(result).isEqualTo(Optional.empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void missingParameterFromSystemPropertyThroughPlaceholder() {
|
||||
String expected = "sysbar";
|
||||
System.setProperty("systemProperty", expected);
|
||||
Message<byte[]> message = MessageBuilder.withPayload(new byte[0]).build();
|
||||
MethodParameter param = this.resolvable.annot(header("#{systemProperties.systemProperty}")).arg();
|
||||
|
||||
assertThatThrownBy(() ->
|
||||
resolveArgument(param, message))
|
||||
.isInstanceOf(MessageHandlingException.class)
|
||||
.hasMessageContaining(expected);
|
||||
|
||||
System.clearProperty("systemProperty");
|
||||
}
|
||||
|
||||
@Test
|
||||
void notNullablePrimitiveParameterFromSystemPropertyThroughPlaceholder() {
|
||||
String expected = "sysbar";
|
||||
System.setProperty("systemProperty", expected);
|
||||
Message<byte[]> message = MessageBuilder.withPayload(new byte[0]).build();
|
||||
MethodParameter param = this.resolvable.annot(header("${systemProperty}").required(false)).arg();
|
||||
|
||||
assertThatThrownBy(() ->
|
||||
resolver.resolveArgument(param, message))
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining(expected);
|
||||
|
||||
System.clearProperty("systemProperty");
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({"unchecked", "ConstantConditions"})
|
||||
private <T> T resolveArgument(MethodParameter param, Message<?> message) {
|
||||
return (T) this.resolver.resolveArgument(param, message).block(Duration.ofSeconds(5));
|
||||
@@ -165,7 +197,8 @@ class HeaderMethodArgumentResolverTests {
|
||||
@Header(name = "#{systemProperties.systemProperty}") String param4,
|
||||
String param5,
|
||||
@Header("foo") Optional<String> param6,
|
||||
@Header("nativeHeaders.param1") String nativeHeaderParam1) {
|
||||
@Header("nativeHeaders.param1") String nativeHeaderParam1,
|
||||
@Header(name = "${systemProperty}", required = false) int primitivePlaceholderParam) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.messaging.support.NativeMessageHeaderAccessor;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.springframework.messaging.handler.annotation.MessagingPredicates.header;
|
||||
import static org.springframework.messaging.handler.annotation.MessagingPredicates.headerPlain;
|
||||
|
||||
@@ -137,6 +138,36 @@ class HeaderMethodArgumentResolverTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void missingParameterFromSystemPropertyThroughPlaceholder() {
|
||||
String expected = "sysbar";
|
||||
System.setProperty("systemProperty", expected);
|
||||
Message<byte[]> message = MessageBuilder.withPayload(new byte[0]).build();
|
||||
MethodParameter param = this.resolvable.annot(header("#{systemProperties.systemProperty}")).arg();
|
||||
|
||||
assertThatThrownBy(() ->
|
||||
resolver.resolveArgument(param, message))
|
||||
.isInstanceOf(MessageHandlingException.class)
|
||||
.hasMessageContaining(expected);
|
||||
|
||||
System.clearProperty("systemProperty");
|
||||
}
|
||||
|
||||
@Test
|
||||
void notNullablePrimitiveParameterFromSystemPropertyThroughPlaceholder() {
|
||||
String expected = "sysbar";
|
||||
System.setProperty("systemProperty", expected);
|
||||
Message<byte[]> message = MessageBuilder.withPayload(new byte[0]).build();
|
||||
MethodParameter param = this.resolvable.annot(header("${systemProperty}").required(false)).arg();
|
||||
|
||||
assertThatThrownBy(() ->
|
||||
resolver.resolveArgument(param, message))
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining(expected);
|
||||
|
||||
System.clearProperty("systemProperty");
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveOptionalHeaderWithValue() throws Exception {
|
||||
Message<String> message = MessageBuilder.withPayload("foo").setHeader("foo", "bar").build();
|
||||
@@ -162,7 +193,8 @@ class HeaderMethodArgumentResolverTests {
|
||||
@Header(name = "#{systemProperties.systemProperty}") String param4,
|
||||
String param5,
|
||||
@Header("foo") Optional<String> param6,
|
||||
@Header("nativeHeaders.param1") String nativeHeaderParam1) {
|
||||
@Header("nativeHeaders.param1") String nativeHeaderParam1,
|
||||
@Header(name = "${systemProperty}", required = false) int primitivePlaceholderParam) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user