Merge branch '6.2.x'

This commit is contained in:
rstoyanchev
2025-04-25 21:33:03 +01:00
9 changed files with 176 additions and 31 deletions
@@ -85,7 +85,8 @@ public final class RestClientAdapter implements HttpExchangeAdapter {
return newRequest(values).retrieve().toEntity(bodyType);
}
private RestClient.RequestBodySpec newRequest(HttpRequestValues values) {
@SuppressWarnings("unchecked")
private <B> RestClient.RequestBodySpec newRequest(HttpRequestValues values) {
HttpMethod httpMethod = values.getHttpMethod();
Assert.notNull(httpMethod, "HttpMethod is required");
@@ -127,8 +128,14 @@ public final class RestClientAdapter implements HttpExchangeAdapter {
bodySpec.attributes(attributes -> attributes.putAll(values.getAttributes()));
if (values.getBodyValue() != null) {
bodySpec.body(values.getBodyValue());
B body = (B) values.getBodyValue();
if (body != null) {
if (values.getBodyValueType() != null) {
bodySpec.body(body, (ParameterizedTypeReference<? super B>) values.getBodyValueType());
}
else {
bodySpec.body(body);
}
}
return bodySpec;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2025 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.
@@ -86,7 +86,7 @@ public final class RestTemplateAdapter implements HttpExchangeAdapter {
return this.restTemplate.exchange(newRequest(values), bodyType);
}
private RequestEntity<?> newRequest(HttpRequestValues values) {
private <B> RequestEntity<?> newRequest(HttpRequestValues values) {
HttpMethod httpMethod = values.getHttpMethod();
Assert.notNull(httpMethod, "HttpMethod is required");
@@ -120,11 +120,16 @@ public final class RestTemplateAdapter implements HttpExchangeAdapter {
builder.header(HttpHeaders.COOKIE, String.join("; ", cookies));
}
if (values.getBodyValue() != null) {
return builder.body(values.getBodyValue());
Object body = values.getBodyValue();
if (body == null) {
return builder.build();
}
return builder.build();
if (values.getBodyValueType() != null) {
return builder.body(body, values.getBodyValueType().getType());
}
return builder.body(body);
}
@@ -26,6 +26,7 @@ import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@@ -74,6 +75,8 @@ public class HttpRequestValues {
private final @Nullable Object bodyValue;
private @Nullable ParameterizedTypeReference<?> bodyValueType;
/**
* Construct {@link HttpRequestValues}.
@@ -176,6 +179,14 @@ public class HttpRequestValues {
return this.bodyValue;
}
/**
* Return the type for the {@linkplain #getBodyValue() body value}.
* @since 6.2.7
*/
public @Nullable ParameterizedTypeReference<?> getBodyValueType() {
return this.bodyValueType;
}
/**
* Return a builder for {@link HttpRequestValues}.
@@ -264,6 +275,8 @@ public class HttpRequestValues {
private @Nullable Object bodyValue;
private @Nullable ParameterizedTypeReference<?> bodyValueType;
protected Builder() {
}
@@ -417,6 +430,15 @@ public class HttpRequestValues {
this.bodyValue = bodyValue;
}
/**
* Variant of {@link #setBodyValue(Object)} with the body type.
* @since 6.2.7
*/
public void setBodyValue(@Nullable Object bodyValue, @Nullable ParameterizedTypeReference<?> valueType) {
setBodyValue(bodyValue);
this.bodyValueType = valueType;
}
// Implementation of {@link Metadata} methods
@@ -489,9 +511,14 @@ public class HttpRequestValues {
Map<String, Object> attributes = (this.attributes != null ?
new HashMap<>(this.attributes) : Collections.emptyMap());
return createRequestValues(
HttpRequestValues requestValues = createRequestValues(
this.httpMethod, uri, uriBuilderFactory, uriTemplate, uriVars,
headers, cookies, this.version, attributes, bodyValue);
// In 6.2.x only, temporarily work around protected methods
requestValues.bodyValueType = this.bodyValueType;
return requestValues;
}
protected boolean hasParts() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -83,15 +83,16 @@ public class RequestBodyArgumentResolver implements HttpServiceArgumentResolver
if (this.reactiveAdapterRegistry != null) {
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(parameter.getParameterType());
if (adapter != null) {
MethodParameter nestedParameter = parameter.nested();
MethodParameter nestedParam = parameter.nested();
String message = "Async type for @RequestBody should produce value(s)";
Assert.isTrue(!adapter.isNoValue(), message);
Assert.isTrue(nestedParameter.getNestedParameterType() != Void.class, message);
Assert.isTrue(nestedParam.getNestedParameterType() != Void.class, message);
if (requestValues instanceof ReactiveHttpRequestValues.Builder reactiveRequestValues) {
reactiveRequestValues.setBodyPublisher(
adapter.toPublisher(argument), asParameterizedTypeRef(nestedParameter));
if (requestValues instanceof ReactiveHttpRequestValues.Builder rrv) {
rrv.setBodyPublisher(
adapter.toPublisher(argument),
ParameterizedTypeReference.forType(nestedParam.getNestedGenericParameterType()));
}
else {
throw new IllegalStateException(
@@ -103,12 +104,8 @@ public class RequestBodyArgumentResolver implements HttpServiceArgumentResolver
}
// Not a reactive type
requestValues.setBodyValue(argument);
requestValues.setBodyValue(argument, ParameterizedTypeReference.forType(parameter.getGenericParameterType()));
return true;
}
private static ParameterizedTypeReference<Object> asParameterizedTypeRef(MethodParameter nestedParam) {
return ParameterizedTypeReference.forType(nestedParam.getNestedGenericParameterType());
}
}