Update after review

See gh-28386
This commit is contained in:
rstoyanchev
2022-04-26 16:28:56 +01:00
parent bb44c0e13a
commit 564f8ba7a0
18 changed files with 224 additions and 218 deletions

View File

@@ -26,7 +26,7 @@ import org.springframework.core.annotation.AliasFor;
/**
* Shortcut for {@link HttpRequest} for HTTP GET requests.
* Shortcut for {@link HttpExchange} for HTTP GET requests.
*
* @author Rossen Stoyanchev
* @since 6.0
@@ -34,25 +34,25 @@ import org.springframework.core.annotation.AliasFor;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@HttpRequest(method = "GET")
public @interface GetRequest {
@HttpExchange(method = "GET")
public @interface GetExchange {
/**
* Alias for {@link HttpRequest#value}.
* Alias for {@link HttpExchange#value}.
*/
@AliasFor(annotation = HttpRequest.class)
@AliasFor(annotation = HttpExchange.class)
String value() default "";
/**
* Alias for {@link HttpRequest#url()}.
* Alias for {@link HttpExchange#url()}.
*/
@AliasFor(annotation = HttpRequest.class)
@AliasFor(annotation = HttpExchange.class)
String url() default "";
/**
* Alias for {@link HttpRequest#accept()}.
* Alias for {@link HttpExchange#accept()}.
*/
@AliasFor(annotation = HttpRequest.class)
@AliasFor(annotation = HttpExchange.class)
String[] accept() default {};
}

View File

@@ -42,7 +42,7 @@ import org.springframework.web.bind.annotation.Mapping;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface HttpRequest {
public @interface HttpExchange {
/**
* This is an alias for {@link #url}.
@@ -52,7 +52,7 @@ public @interface HttpRequest {
/**
* The URL for the request, either a full URL or a path only that is relative
* to a URL declared in a type-level {@code @HttpRequest}, and/or a globally
* to a URL declared in a type-level {@code @HttpExchange}, and/or a globally
* configured base URL.
* <p>By default, this is empty.
*/
@@ -67,7 +67,6 @@ public @interface HttpRequest {
*/
String method() default "";
/**
* The media type for the {@code "Content-Type"} header.
* <p>Supported at the type level as well as at the method level, in which

View File

@@ -24,8 +24,9 @@ import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
/**
* Shortcut for {@link HttpRequest} for HTTP POST requests.
* Shortcut for {@link HttpExchange} for HTTP POST requests.
*
* @author Rossen Stoyanchev
* @since 6.0
@@ -33,31 +34,31 @@ import org.springframework.core.annotation.AliasFor;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@HttpRequest(method = "POST")
public @interface PostRequest {
@HttpExchange(method = "POST")
public @interface PostExchange {
/**
* Alias for {@link HttpRequest#value}.
* Alias for {@link HttpExchange#value}.
*/
@AliasFor(annotation = HttpRequest.class)
@AliasFor(annotation = HttpExchange.class)
String value() default "";
/**
* Alias for {@link HttpRequest#url()}.
* Alias for {@link HttpExchange#url()}.
*/
@AliasFor(annotation = HttpRequest.class)
@AliasFor(annotation = HttpExchange.class)
String url() default "";
/**
* Alias for {@link HttpRequest#contentType()}.
* Alias for {@link HttpExchange#contentType()}.
*/
@AliasFor(annotation = HttpRequest.class)
@AliasFor(annotation = HttpExchange.class)
String contentType() default "";
/**
* Alias for {@link HttpRequest#accept()}.
* Alias for {@link HttpExchange#accept()}.
*/
@AliasFor(annotation = HttpRequest.class)
@AliasFor(annotation = HttpExchange.class)
String[] accept() default {};
}

View File

@@ -24,8 +24,9 @@ import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
/**
* Shortcut for {@link HttpRequest} for HTTP PUT requests.
* Shortcut for {@link HttpExchange} for HTTP PUT requests.
*
* @author Rossen Stoyanchev
* @since 6.0
@@ -33,25 +34,25 @@ import org.springframework.core.annotation.AliasFor;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@HttpRequest(method = "PUT")
public @interface PutRequest {
@HttpExchange(method = "PUT")
public @interface PutExchange {
/**
* Alias for {@link HttpRequest#value}.
* Alias for {@link HttpExchange#value}.
*/
@AliasFor(annotation = HttpRequest.class)
@AliasFor(annotation = HttpExchange.class)
String[] value() default {};
/**
* Alias for {@link HttpRequest#url()}.
* Alias for {@link HttpExchange#url()}.
*/
@AliasFor(annotation = HttpRequest.class)
@AliasFor(annotation = HttpExchange.class)
String[] url() default {};
/**
* Alias for {@link HttpRequest#contentType()}.
* Alias for {@link HttpExchange#contentType()}.
*/
@AliasFor(annotation = HttpRequest.class)
@AliasFor(annotation = HttpExchange.class)
String contentType() default "";
}

View File

@@ -25,26 +25,26 @@ import org.springframework.http.ResponseEntity;
/**
* Decouple an {@link HttpServiceProxyFactory#createService(Class) HTTP Service proxy}
* from the underlying HTTP client.
* Contract to abstract the underlying HTTP client and decouple it from the
* {@link HttpServiceProxyFactory#createClient(Class) HTTP Service proxy}.
*
* @author Rossen Stoyanchev
* @since 6.0
*/
public interface HttpClientAdapter {
Mono<Void> requestToVoid(HttpRequestDefinition requestDefinition);
Mono<Void> requestToVoid(HttpRequestSpec spec);
Mono<HttpHeaders> requestToHeaders(HttpRequestDefinition requestDefinition);
Mono<HttpHeaders> requestToHeaders(HttpRequestSpec spec);
<T> Mono<T> requestToBody(HttpRequestDefinition requestDefinition, ParameterizedTypeReference<T> bodyType);
<T> Mono<T> requestToBody(HttpRequestSpec spec, ParameterizedTypeReference<T> bodyType);
<T> Flux<T> requestToBodyFlux(HttpRequestDefinition requestDefinition, ParameterizedTypeReference<T> bodyType);
<T> Flux<T> requestToBodyFlux(HttpRequestSpec spec, ParameterizedTypeReference<T> bodyType);
Mono<ResponseEntity<Void>> requestToBodilessEntity(HttpRequestDefinition requestDefinition);
Mono<ResponseEntity<Void>> requestToBodilessEntity(HttpRequestSpec spec);
<T> Mono<ResponseEntity<T>> requestToEntity(HttpRequestDefinition requestDefinition, ParameterizedTypeReference<T> bodyType);
<T> Mono<ResponseEntity<T>> requestToEntity(HttpRequestSpec spec, ParameterizedTypeReference<T> bodyType);
<T> Mono<ResponseEntity<Flux<T>>> requestToEntityFlux(HttpRequestDefinition requestDefinition, ParameterizedTypeReference<T> bodyType);
<T> Mono<ResponseEntity<Flux<T>>> requestToEntityFlux(HttpRequestSpec spec, ParameterizedTypeReference<T> bodyType);
}

View File

@@ -25,20 +25,20 @@ import org.springframework.lang.Nullable;
/**
* {@link HttpServiceMethodArgumentResolver} that resolves the target
* {@link HttpServiceArgumentResolver} that resolves the target
* request's HTTP method from an {@link HttpMethod} argument.
*
* @author Olga Maciaszek-Sharma
* @since 6.0
*/
public class HttpMethodArgumentResolver implements HttpServiceMethodArgumentResolver {
public class HttpMethodArgumentResolver implements HttpServiceArgumentResolver {
private static final Log logger = LogFactory.getLog(HttpMethodArgumentResolver.class);
@Override
public void resolve(
@Nullable Object argument, MethodParameter parameter, HttpRequestDefinition requestDefinition) {
@Nullable Object argument, MethodParameter parameter, HttpRequestSpec requestSpec) {
if (argument == null) {
return;
@@ -47,7 +47,7 @@ public class HttpMethodArgumentResolver implements HttpServiceMethodArgumentReso
if (logger.isTraceEnabled()) {
logger.trace("Resolved HTTP method to: " + httpMethod.name());
}
requestDefinition.setHttpMethod(httpMethod);
requestSpec.setHttpMethod(httpMethod);
}
}

View File

@@ -30,7 +30,6 @@ import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
@@ -39,15 +38,15 @@ import org.springframework.util.MultiValueMap;
/**
* Container for HTTP request values accumulated from an
* {@link HttpRequest @HttpRequest}-annotated method and arguments passed to it.
* This allows an {@link HttpClientAdapter} adapt these inputs as it sees fit
* to the API of the underlying client.
* Container for HTTP request values extracted from an
* {@link org.springframework.web.service.annotation.HttpExchange @HttpExchange}-annotated
* method and argument values passed to it. This is then given to
* {@link HttpClientAdapter} to adapt to the underlying HTTP client.
*
* @author Rossen Stoyanchev
* @since 6.0
*/
public class HttpRequestDefinition {
public class HttpRequestSpec {
private static final MultiValueMap<String, String> EMPTY_COOKIES_MAP =
CollectionUtils.toMultiValueMap(Collections.emptyMap());
@@ -86,6 +85,10 @@ public class HttpRequestDefinition {
private boolean complete;
public HttpRequestSpec() {
}
public void setUri(URI uri) {
checkComplete();
this.uri = uri;
@@ -175,6 +178,8 @@ public class HttpRequestDefinition {
void setComplete() {
this.complete = true;
this.uriVariables = (this.uriVariables != null ?
Collections.unmodifiableMap(this.uriVariables) : Collections.emptyMap());

View File

@@ -18,24 +18,24 @@ package org.springframework.web.service.invoker;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.web.service.annotation.HttpRequest;
import org.springframework.web.service.annotation.HttpExchange;
/**
* Resolve an argument from an {@link HttpRequest @HttpRequest} annotated method
* Resolve an argument from an {@link HttpExchange @HttpExchange}-annotated method
* to one or more HTTP request values.
*
* @author Rossen Stoyanchev
* @since 6.0
*/
public interface HttpServiceMethodArgumentResolver {
public interface HttpServiceArgumentResolver {
/**
* Resolve the argument value.
* @param argument the argument value
* @param parameter the method parameter for the argument
* @param requestDefinition container to add HTTP request values to
* @param requestSpec container to add HTTP request values to
*/
void resolve(@Nullable Object argument, MethodParameter parameter, HttpRequestDefinition requestDefinition);
void resolve(@Nullable Object argument, MethodParameter parameter, HttpRequestSpec requestSpec);
}

View File

@@ -43,12 +43,12 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.service.annotation.HttpRequest;
import org.springframework.web.service.annotation.HttpExchange;
/**
* Implements the invocation of an {@link HttpRequest @HttpRequest} annotated,
* {@link HttpServiceProxyFactory#createService(Class) HTTP Service proxy} method
* Implements the invocation of an {@link HttpExchange @HttpExchange}-annotated,
* {@link HttpServiceProxyFactory#createClient(Class) HTTP Service proxy} method
* by delegating to an {@link HttpClientAdapter} to perform actual requests.
*
* @author Rossen Stoyanchev
@@ -60,22 +60,22 @@ final class HttpServiceMethod {
private final MethodParameter[] parameters;
private final List<HttpServiceMethodArgumentResolver> argumentResolvers;
private final List<HttpServiceArgumentResolver> argumentResolvers;
private final HttpRequestDefinitionFactory requestDefinitionFactory;
private final HttpRequestSpecFactory requestSpecFactory;
private final ResponseFunction responseFunction;
HttpServiceMethod(
Method method, Class<?> containingClass, List<HttpServiceMethodArgumentResolver> argumentResolvers,
Method method, Class<?> containingClass, List<HttpServiceArgumentResolver> argumentResolvers,
HttpClientAdapter client, ReactiveAdapterRegistry reactiveRegistry,
Duration blockTimeout) {
this.method = method;
this.parameters = initMethodParameters(method);
this.argumentResolvers = argumentResolvers;
this.requestDefinitionFactory = HttpRequestDefinitionFactory.create(method, containingClass);
this.requestSpecFactory = HttpRequestSpecFactory.create(method, containingClass);
this.responseFunction = ResponseFunction.create(client, method, reactiveRegistry, blockTimeout);
}
@@ -96,34 +96,34 @@ final class HttpServiceMethod {
@Nullable
public Object invoke(Object[] arguments) {
HttpRequestDefinition requestDefinition = this.requestDefinitionFactory.initializeRequest();
applyArguments(requestDefinition, arguments);
requestDefinition.setComplete();
return this.responseFunction.execute(requestDefinition);
HttpRequestSpec requestSpec = this.requestSpecFactory.initializeRequestSpec();
applyArguments(requestSpec, arguments);
requestSpec.setComplete();
return this.responseFunction.execute(requestSpec);
}
private void applyArguments(HttpRequestDefinition requestDefinition, Object[] arguments) {
private void applyArguments(HttpRequestSpec requestSpec, Object[] arguments) {
Assert.isTrue(arguments.length == this.parameters.length, "Method argument mismatch");
for (int i = 0; i < this.parameters.length; i++) {
Object argumentValue = arguments[i];
ParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
this.parameters[i].initParameterNameDiscovery(nameDiscoverer);
for (HttpServiceMethodArgumentResolver resolver : this.argumentResolvers) {
resolver.resolve(argumentValue, this.parameters[i], requestDefinition);
for (HttpServiceArgumentResolver resolver : this.argumentResolvers) {
resolver.resolve(argumentValue, this.parameters[i], requestSpec);
}
}
}
/**
* Factory for an {@link HttpRequestDefinition} with values extracted from
* the type and method-level {@link HttpRequest @HttpRequest} annotations.
* Factory for an {@link HttpRequestSpec} with values extracted from
* the type and method-level {@link HttpExchange @HttpRequest} annotations.
*/
private record HttpRequestDefinitionFactory(
private record HttpRequestSpecFactory(
@Nullable HttpMethod httpMethod, @Nullable String url,
@Nullable MediaType contentType, @Nullable List<MediaType> acceptMediaTypes) {
private HttpRequestDefinitionFactory(
private HttpRequestSpecFactory(
@Nullable HttpMethod httpMethod, @Nullable String url,
@Nullable MediaType contentType, @Nullable List<MediaType> acceptMediaTypes) {
@@ -133,31 +133,31 @@ final class HttpServiceMethod {
this.acceptMediaTypes = acceptMediaTypes;
}
public HttpRequestDefinition initializeRequest() {
HttpRequestDefinition requestDefinition = new HttpRequestDefinition();
public HttpRequestSpec initializeRequestSpec() {
HttpRequestSpec requestSpec = new HttpRequestSpec();
if (this.httpMethod != null) {
requestDefinition.setHttpMethod(this.httpMethod);
requestSpec.setHttpMethod(this.httpMethod);
}
if (this.url != null) {
requestDefinition.setUriTemplate(this.url);
requestSpec.setUriTemplate(this.url);
}
if (this.contentType != null) {
requestDefinition.getHeaders().setContentType(this.contentType);
requestSpec.getHeaders().setContentType(this.contentType);
}
if (this.acceptMediaTypes != null) {
requestDefinition.getHeaders().setAccept(this.acceptMediaTypes);
requestSpec.getHeaders().setAccept(this.acceptMediaTypes);
}
return requestDefinition;
return requestSpec;
}
/**
* Introspect the method and create the request factory for it.
*/
public static HttpRequestDefinitionFactory create(Method method, Class<?> containingClass) {
public static HttpRequestSpecFactory create(Method method, Class<?> containingClass) {
HttpRequest annot1 = AnnotatedElementUtils.findMergedAnnotation(containingClass, HttpRequest.class);
HttpRequest annot2 = AnnotatedElementUtils.findMergedAnnotation(method, HttpRequest.class);
HttpExchange annot1 = AnnotatedElementUtils.findMergedAnnotation(containingClass, HttpExchange.class);
HttpExchange annot2 = AnnotatedElementUtils.findMergedAnnotation(method, HttpExchange.class);
Assert.notNull(annot2, "Expected HttpRequest annotation");
@@ -166,12 +166,12 @@ final class HttpServiceMethod {
MediaType contentType = initContentType(annot1, annot2);
List<MediaType> acceptableMediaTypes = initAccept(annot1, annot2);
return new HttpRequestDefinitionFactory(httpMethod, url, contentType, acceptableMediaTypes);
return new HttpRequestSpecFactory(httpMethod, url, contentType, acceptableMediaTypes);
}
@Nullable
private static HttpMethod initHttpMethod(@Nullable HttpRequest typeAnnot, HttpRequest annot) {
private static HttpMethod initHttpMethod(@Nullable HttpExchange typeAnnot, HttpExchange annot) {
String value1 = (typeAnnot != null ? typeAnnot.method() : null);
String value2 = annot.method();
@@ -188,7 +188,7 @@ final class HttpServiceMethod {
}
@Nullable
private static String initUrl(@Nullable HttpRequest typeAnnot, HttpRequest annot) {
private static String initUrl(@Nullable HttpExchange typeAnnot, HttpExchange annot) {
String url1 = (typeAnnot != null ? typeAnnot.url() : null);
String url2 = annot.url();
@@ -208,7 +208,7 @@ final class HttpServiceMethod {
}
@Nullable
private static MediaType initContentType(@Nullable HttpRequest typeAnnot, HttpRequest annot) {
private static MediaType initContentType(@Nullable HttpExchange typeAnnot, HttpExchange annot) {
String value1 = (typeAnnot != null ? typeAnnot.contentType() : null);
String value2 = annot.contentType();
@@ -225,7 +225,7 @@ final class HttpServiceMethod {
}
@Nullable
private static List<MediaType> initAccept(@Nullable HttpRequest typeAnnot, HttpRequest annot) {
private static List<MediaType> initAccept(@Nullable HttpExchange typeAnnot, HttpExchange annot) {
String[] value1 = (typeAnnot != null ? typeAnnot.accept() : null);
String[] value2 = annot.accept();
@@ -249,12 +249,12 @@ final class HttpServiceMethod {
* return type blocking if necessary.
*/
private record ResponseFunction(
Function<HttpRequestDefinition, Publisher<?>> responseFunction,
Function<HttpRequestSpec, Publisher<?>> responseFunction,
@Nullable ReactiveAdapter returnTypeAdapter,
boolean blockForOptional, Duration blockTimeout) {
private ResponseFunction(
Function<HttpRequestDefinition, Publisher<?>> responseFunction,
Function<HttpRequestSpec, Publisher<?>> responseFunction,
@Nullable ReactiveAdapter returnTypeAdapter,
boolean blockForOptional, Duration blockTimeout) {
@@ -265,9 +265,9 @@ final class HttpServiceMethod {
}
@Nullable
public Object execute(HttpRequestDefinition requestDefinition) {
public Object execute(HttpRequestSpec requestSpec) {
Publisher<?> responsePublisher = this.responseFunction.apply(requestDefinition);
Publisher<?> responsePublisher = this.responseFunction.apply(requestSpec);
if (this.returnTypeAdapter != null) {
return this.returnTypeAdapter.fromPublisher(responsePublisher);
@@ -293,7 +293,7 @@ final class HttpServiceMethod {
MethodParameter actualParam = (reactiveAdapter != null ? returnParam.nested() : returnParam.nestedIfOptional());
Class<?> actualType = actualParam.getNestedParameterType();
Function<HttpRequestDefinition, Publisher<?>> responseFunction;
Function<HttpRequestSpec, Publisher<?>> responseFunction;
if (actualType.equals(void.class) || actualType.equals(Void.class)) {
responseFunction = client::requestToVoid;
}
@@ -323,7 +323,7 @@ final class HttpServiceMethod {
}
@SuppressWarnings("ConstantConditions")
private static Function<HttpRequestDefinition, Publisher<?>> initResponseEntityFunction(
private static Function<HttpRequestSpec, Publisher<?>> initResponseEntityFunction(
HttpClientAdapter client, MethodParameter methodParam, @Nullable ReactiveAdapter reactiveAdapter) {
if (reactiveAdapter == null) {
@@ -349,7 +349,7 @@ final class HttpServiceMethod {
});
}
private static Function<HttpRequestDefinition, Publisher<?>> initBodyFunction(
private static Function<HttpRequestSpec, Publisher<?>> initBodyFunction(
HttpClientAdapter client, MethodParameter methodParam, @Nullable ReactiveAdapter reactiveAdapter) {
ParameterizedTypeReference<?> bodyType =

View File

@@ -29,18 +29,18 @@ import org.springframework.aop.framework.ProxyFactory;
import org.springframework.core.MethodIntrospector;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.service.annotation.HttpRequest;
import org.springframework.web.service.annotation.HttpExchange;
/**
* Factory to create a proxy for an HTTP service with {@link HttpRequest} methods.
* Factory to create a proxy for an HTTP service with {@link HttpExchange} methods.
*
* @author Rossen Stoyanchev
* @since 6.0
*/
public class HttpServiceProxyFactory {
private final List<HttpServiceMethodArgumentResolver> argumentResolvers;
private final List<HttpServiceArgumentResolver> argumentResolvers;
private final HttpClientAdapter clientAdapter;
@@ -50,7 +50,7 @@ public class HttpServiceProxyFactory {
public HttpServiceProxyFactory(
List<HttpServiceMethodArgumentResolver> argumentResolvers, HttpClientAdapter clientAdapter,
List<HttpServiceArgumentResolver> argumentResolvers, HttpClientAdapter clientAdapter,
ReactiveAdapterRegistry reactiveAdapterRegistry, Duration blockTimeout) {
this.argumentResolvers = argumentResolvers;
@@ -66,7 +66,7 @@ public class HttpServiceProxyFactory {
* @param <S> the service type
* @return the created proxy
*/
public <S> S createService(Class<S> serviceType) {
public <S> S createClient(Class<S> serviceType) {
List<HttpServiceMethod> methods =
MethodIntrospector.selectMethods(serviceType, this::isHttpRequestMethod)
@@ -78,7 +78,7 @@ public class HttpServiceProxyFactory {
}
private boolean isHttpRequestMethod(Method method) {
return AnnotatedElementUtils.hasAnnotation(method, HttpRequest.class);
return AnnotatedElementUtils.hasAnnotation(method, HttpExchange.class);
}
private HttpServiceMethod initServiceMethod(Method method, Class<?> serviceType) {
@@ -93,16 +93,16 @@ public class HttpServiceProxyFactory {
*/
private static final class HttpServiceMethodInterceptor implements MethodInterceptor {
private final Map<Method, HttpServiceMethod> serviceMethodMap = new HashMap<>();
private final Map<Method, HttpServiceMethod> httpServiceMethods = new HashMap<>();
private HttpServiceMethodInterceptor(List<HttpServiceMethod> methods) {
methods.forEach(serviceMethod -> this.serviceMethodMap.put(serviceMethod.getMethod(), serviceMethod));
methods.forEach(serviceMethod -> this.httpServiceMethods.put(serviceMethod.getMethod(), serviceMethod));
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
public Object invoke(MethodInvocation invocation) {
Method method = invocation.getMethod();
HttpServiceMethod httpServiceMethod = this.serviceMethodMap.get(method);
HttpServiceMethod httpServiceMethod = this.httpServiceMethods.get(method);
return httpServiceMethod.invoke(invocation.getArguments());
}

View File

@@ -31,7 +31,7 @@ import org.springframework.web.bind.annotation.PathVariable;
/**
* An implementation of {@link HttpServiceMethodArgumentResolver} that resolves
* An implementation of {@link HttpServiceArgumentResolver} that resolves
* request path variables based on method arguments annotated
* with {@link PathVariable}. {@code null} values are allowed only
* if {@link PathVariable#required()} is {@code true}.
@@ -39,7 +39,7 @@ import org.springframework.web.bind.annotation.PathVariable;
* @author Olga Maciaszek-Sharma
* @since 6.0
*/
public class PathVariableArgumentResolver implements HttpServiceMethodArgumentResolver {
public class PathVariableArgumentResolver implements HttpServiceArgumentResolver {
private static final Log logger = LogFactory.getLog(PathVariableArgumentResolver.class);
@@ -56,7 +56,7 @@ public class PathVariableArgumentResolver implements HttpServiceMethodArgumentRe
@SuppressWarnings("unchecked")
@Override
public void resolve(
@Nullable Object argument, MethodParameter parameter, HttpRequestDefinition requestDefinition) {
@Nullable Object argument, MethodParameter parameter, HttpRequestSpec requestSpec) {
PathVariable annotation = parameter.getParameterAnnotation(PathVariable.class);
if (annotation == null) {
@@ -67,19 +67,19 @@ public class PathVariableArgumentResolver implements HttpServiceMethodArgumentRe
if (argument != null) {
Assert.isInstanceOf(Map.class, argument);
((Map<String, ?>) argument).forEach((key, value) ->
addUriParameter(key, value, annotation.required(), requestDefinition));
addUriParameter(key, value, annotation.required(), requestSpec));
}
}
else {
String name = StringUtils.hasText(annotation.value()) ? annotation.value() : annotation.name();
name = StringUtils.hasText(name) ? name : parameter.getParameterName();
Assert.notNull(name, "Failed to determine path variable name for parameter: " + parameter);
addUriParameter(name, argument, annotation.required(), requestDefinition);
addUriParameter(name, argument, annotation.required(), requestSpec);
}
}
private void addUriParameter(
String name, @Nullable Object value, boolean required, HttpRequestDefinition requestDefinition) {
String name, @Nullable Object value, boolean required, HttpRequestSpec requestSpec) {
if (value instanceof Optional) {
value = ((Optional<?>) value).orElse(null);
@@ -98,7 +98,7 @@ public class PathVariableArgumentResolver implements HttpServiceMethodArgumentRe
logger.trace("Resolved path variable '" + name + "' to " + value);
}
requestDefinition.getUriVariables().put(name, (String) value);
requestSpec.getUriVariables().put(name, (String) value);
}
}

View File

@@ -1,6 +1,6 @@
/**
* Support to create a client proxy for an HTTP service annotated with
* {@link org.springframework.web.service.annotation.HttpRequest} methods.
* {@link org.springframework.web.service.annotation.HttpExchange} methods.
*/
@NonNullApi
@NonNullFields