Merge branch '6.1.x'

# Conflicts:
#	spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java
#	spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java
#	spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java
This commit is contained in:
Juergen Hoeller
2024-04-10 18:29:48 +02:00
7 changed files with 31 additions and 38 deletions

View File

@@ -75,8 +75,8 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
private static final String COROUTINES_FLOW_CLASS_NAME = "kotlinx.coroutines.flow.Flow";
private static final boolean coroutinesReactorPresent = ClassUtils.isPresent("kotlinx.coroutines.reactor.MonoKt",
JdkDynamicAopProxy.class.getClassLoader());;
private static final boolean coroutinesReactorPresent = ClassUtils.isPresent(
"kotlinx.coroutines.reactor.MonoKt", JdkDynamicAopProxy.class.getClassLoader());
/** We use a static Log to avoid serialization issues. */
private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);

View File

@@ -65,8 +65,9 @@ import org.springframework.util.ReflectionUtils;
*/
public abstract class AopUtils {
private static final boolean coroutinesReactorPresent = ClassUtils.isPresent("kotlinx.coroutines.reactor.MonoKt",
AopUtils.class.getClassLoader());;
private static final boolean coroutinesReactorPresent = ClassUtils.isPresent(
"kotlinx.coroutines.reactor.MonoKt", AopUtils.class.getClassLoader());
/**
* Check whether the given object is a JDK dynamic proxy or a CGLIB proxy.
@@ -353,8 +354,8 @@ public abstract class AopUtils {
// Use reflection to invoke the method.
try {
ReflectionUtils.makeAccessible(method);
return coroutinesReactorPresent && KotlinDetector.isSuspendingFunction(method) ?
KotlinDelegate.invokeSuspendingFunction(method, target, args) : method.invoke(target, args);
return (coroutinesReactorPresent && KotlinDetector.isSuspendingFunction(method) ?
KotlinDelegate.invokeSuspendingFunction(method, target, args) : method.invoke(target, args));
}
catch (InvocationTargetException ex) {
// Invoked method threw a checked exception.

View File

@@ -35,8 +35,8 @@ import org.springframework.lang.Nullable;
*/
class KotlinReflectionBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {
@Nullable
@Override
@Nullable
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
Class<?> beanClass = registeredBean.getBeanClass();
if (KotlinDetector.isKotlinType(beanClass)) {
@@ -45,6 +45,7 @@ class KotlinReflectionBeanRegistrationAotProcessor implements BeanRegistrationAo
return null;
}
private static class AotContribution implements BeanRegistrationAotContribution {
private final Class<?> beanClass;

View File

@@ -124,6 +124,7 @@ class ServletServerHttpRequestTests {
assertThat(headers).as("No HttpHeaders returned").isNotNull();
assertThat(headers.containsKey(headerName)).as("Invalid headers returned").isTrue();
List<String> headerValues = headers.get(headerName);
assertThat(headerValues).as("No header values returned").isNotNull();
assertThat(headerValues.size()).as("Invalid header values returned").isEqualTo(2);
assertThat(headerValues.contains(headerValue1)).as("Invalid header values returned").isTrue();
assertThat(headerValues.contains(headerValue2)).as("Invalid header values returned").isTrue();
@@ -150,7 +151,7 @@ class ServletServerHttpRequestTests {
assertThat(headers.getContentType()).isNull();
}
@Test // gh-27957
@Test // gh-27957
void getHeadersWithWildcardContentType() {
mockRequest.setContentType("*/*");
mockRequest.removeHeader("Content-Type");
@@ -166,7 +167,7 @@ class ServletServerHttpRequestTests {
assertThat(result).as("Invalid content returned").isEqualTo(content);
}
@Test // gh-13318
@Test // gh-13318
void getFormBody() throws IOException {
mockRequest.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
mockRequest.setMethod("POST");
@@ -189,7 +190,7 @@ class ServletServerHttpRequestTests {
assertThat(result).as("Invalid content returned").isEqualTo(content);
}
@Test // gh-31327
@Test // gh-31327
void getFormBodyWhenQueryParamsAlsoPresent() throws IOException {
mockRequest.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
mockRequest.setMethod("POST");
@@ -203,7 +204,7 @@ class ServletServerHttpRequestTests {
assertThat(result).as("Invalid content returned").isEqualTo(content);
}
@Test // gh-32471
@Test // gh-32471
void getFormBodyWhenNotEncodedCharactersPresent() throws IOException {
mockRequest.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
mockRequest.setMethod("POST");

View File

@@ -186,7 +186,7 @@ class RequestParamMethodArgumentResolverTests {
assertThat(result).asInstanceOf(array(String[].class)).containsExactly(expected);
}
@Test // gh-32577
@Test // gh-32577
void resolveStringArrayWithEmptyArraySuffix() throws Exception {
String[] expected = new String[] {"foo", "bar"};
request.addParameter("name[]", expected[0]);
@@ -221,7 +221,6 @@ class RequestParamMethodArgumentResolverTests {
MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(List.class, MultipartFile.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertThat(result).asInstanceOf(LIST).containsExactly(expected1, expected2);
}
@@ -248,7 +247,6 @@ class RequestParamMethodArgumentResolverTests {
MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(MultipartFile[].class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertThat(result).asInstanceOf(array(MultipartFile[].class)).containsExactly(expected1, expected2);
}
@@ -274,7 +272,6 @@ class RequestParamMethodArgumentResolverTests {
MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(Part.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertThat(result).asInstanceOf(type(Part.class)).isEqualTo(expected);
}
@@ -292,7 +289,6 @@ class RequestParamMethodArgumentResolverTests {
MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(List.class, Part.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertThat(result).asInstanceOf(LIST).containsExactly(expected1, expected2);
}
@@ -323,7 +319,6 @@ class RequestParamMethodArgumentResolverTests {
MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(Part[].class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertThat(result).asInstanceOf(array(Part[].class)).containsExactly(expected1, expected2);
}
@@ -442,7 +437,6 @@ class RequestParamMethodArgumentResolverTests {
WebDataBinderFactory binderFactory = mock();
given(binderFactory.createBinder(webRequest, null, "stringNotAnnot")).willReturn(binder);
request.addParameter("stringNotAnnot", "");
MethodParameter param = this.testMethod.annotNotPresent(RequestParam.class).arg(String.class);
@@ -456,7 +450,6 @@ class RequestParamMethodArgumentResolverTests {
WebDataBinderFactory binderFactory = mock();
given(binderFactory.createBinder(webRequest, null, "booleanParam")).willReturn(binder);
request.addParameter("booleanParam", " ");
MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(Boolean.class);
@@ -471,7 +464,6 @@ class RequestParamMethodArgumentResolverTests {
WebDataBinderFactory binderFactory = mock();
given(binderFactory.createBinder(webRequest, null, "name")).willReturn(binder);
request.addParameter("name", "");
MethodParameter param = this.testMethod.annot(requestParam().notRequired()).arg(String.class);
@@ -479,14 +471,13 @@ class RequestParamMethodArgumentResolverTests {
assertThat(arg).isNull();
}
@Test // gh-29550
@Test // gh-29550
public void missingRequestParamEmptyValueNotRequiredWithDefaultValue() throws Exception {
WebDataBinder binder = new WebRequestDataBinder(null);
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
WebDataBinderFactory binderFactory = mock();
given(binderFactory.createBinder(webRequest, null, "name")).willReturn(binder);
request.addParameter("name", " ");
MethodParameter param = this.testMethod.annot(requestParam().notRequired("bar")).arg(String.class);
@@ -499,7 +490,6 @@ class RequestParamMethodArgumentResolverTests {
request.setParameter("stringNotAnnot", "plainValue");
MethodParameter param = this.testMethod.annotNotPresent(RequestParam.class).arg(String.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertThat(result).isEqualTo("plainValue");
}
@@ -646,7 +636,6 @@ class RequestParamMethodArgumentResolverTests {
MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(Optional.class, MultipartFile.class);
Object result = resolver.resolveArgument(param, null, webRequest, binderFactory);
assertThat(result).asInstanceOf(optional(MultipartFile.class)).contains(expected);
}

View File

@@ -188,8 +188,8 @@ class ControllerAdviceTests {
TestController controller = context.getBean(TestController.class);
controller.setException(exception);
Object actual = handle(adapter, controller, this.postExchange, Duration.ofMillis(100)
, "threadWithArg", String.class).getReturnValue();
Object actual = handle(adapter, controller, this.postExchange, Duration.ofMillis(1000),
"threadWithArg", String.class).getReturnValue();
assertThat(actual).isEqualTo(expected);
}
@@ -242,6 +242,7 @@ class ControllerAdviceTests {
}
}
@Controller
static class TestController {
@@ -249,7 +250,6 @@ class ControllerAdviceTests {
private Throwable exception;
void setValidator(Validator validator) {
this.validator = validator;
}
@@ -258,7 +258,6 @@ class ControllerAdviceTests {
this.exception = exception;
}
@InitBinder
public void initDataBinder(WebDataBinder dataBinder) {
if (this.validator != null) {
@@ -291,6 +290,7 @@ class ControllerAdviceTests {
}
}
@ControllerAdvice
@Order(1)
static class OneControllerAdvice {
@@ -323,6 +323,7 @@ class ControllerAdviceTests {
}
}
@ControllerAdvice
@Order(2)
static class SecondControllerAdvice {

View File

@@ -16,7 +16,6 @@
package org.springframework.web.reactive.result.method.annotation;
import java.time.Duration;
import java.util.Map;
import java.util.Optional;
@@ -29,6 +28,7 @@ import reactor.test.StepVerifier;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.reactive.BindingContext;
@@ -105,12 +105,12 @@ class RequestParamMethodArgumentResolverTests {
@Test
void doesNotSupportReactiveWrapper() {
assertThatIllegalStateException().isThrownBy(() ->
this.resolver.supportsParameter(this.testMethod.annot(requestParam()).arg(Mono.class, String.class)))
.withMessageStartingWith("RequestParamMethodArgumentResolver does not support reactive type wrapper");
assertThatIllegalStateException().isThrownBy(() ->
this.resolver.supportsParameter(this.testMethod.annotNotPresent(RequestParam.class).arg(Mono.class, String.class)))
.withMessageStartingWith("RequestParamMethodArgumentResolver does not support reactive type wrapper");
assertThatIllegalStateException()
.isThrownBy(() -> this.resolver.supportsParameter(this.testMethod.annot(requestParam()).arg(Mono.class, String.class)))
.withMessageStartingWith("RequestParamMethodArgumentResolver does not support reactive type wrapper");
assertThatIllegalStateException()
.isThrownBy(() -> this.resolver.supportsParameter(this.testMethod.annotNotPresent(RequestParam.class).arg(Mono.class, String.class)))
.withMessageStartingWith("RequestParamMethodArgumentResolver does not support reactive type wrapper");
}
@Test
@@ -128,7 +128,7 @@ class RequestParamMethodArgumentResolverTests {
assertThat(result).asInstanceOf(array(String[].class)).containsExactly("foo", "bar");
}
@Test // gh-32577
@Test // gh-32577
void resolveStringArrayWithEmptyArraySuffix() {
MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(String[].class);
MockServerHttpRequest request = MockServerHttpRequest.get("/path?name[]=foo&name[]=bar").build();
@@ -142,7 +142,7 @@ class RequestParamMethodArgumentResolverTests {
assertThat(resolve(param, MockServerWebExchange.from(MockServerHttpRequest.get("/")))).isEqualTo("bar");
}
@Test // SPR-17050
@Test // SPR-17050
public void resolveAndConvertNullValue() {
MethodParameter param = this.testMethod
.annot(requestParam().notRequired())
@@ -152,7 +152,6 @@ class RequestParamMethodArgumentResolverTests {
@Test
void missingRequestParam() {
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/"));
MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(String[].class);
Mono<Object> mono = this.resolver.resolveArgument(param, this.bindContext, exchange);
@@ -214,6 +213,7 @@ class RequestParamMethodArgumentResolverTests {
}
@Nullable
private Object resolve(MethodParameter parameter, ServerWebExchange exchange) {
return this.resolver.resolveArgument(parameter, this.bindContext, exchange).block(Duration.ZERO);
}