Support Coroutines in HttpServiceProxyFactory
See gh-29527
This commit is contained in:
committed by
Sébastien Deleuze
parent
ce85fdc5c7
commit
1d4bf58e8d
@@ -28,6 +28,7 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.KotlinDetector;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.ReactiveAdapter;
|
||||
@@ -83,6 +84,11 @@ final class HttpServiceMethod {
|
||||
if (count == 0) {
|
||||
return new MethodParameter[0];
|
||||
}
|
||||
|
||||
if (KotlinDetector.isSuspendingFunction(method)) {
|
||||
count -= 1;
|
||||
}
|
||||
|
||||
DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||
MethodParameter[] parameters = new MethodParameter[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
@@ -306,6 +312,10 @@ final class HttpServiceMethod {
|
||||
|
||||
MethodParameter returnParam = new MethodParameter(method, -1);
|
||||
Class<?> returnType = returnParam.getParameterType();
|
||||
if (KotlinDetector.isSuspendingFunction(method)) {
|
||||
returnType = Mono.class;
|
||||
}
|
||||
|
||||
ReactiveAdapter reactiveAdapter = reactiveRegistry.getAdapter(returnType);
|
||||
|
||||
MethodParameter actualParam = (reactiveAdapter != null ? returnParam.nested() : returnParam.nestedIfOptional());
|
||||
|
||||
@@ -25,11 +25,15 @@ import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import kotlin.coroutines.Continuation;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.aop.framework.ReflectiveMethodInvocation;
|
||||
import org.springframework.core.CoroutinesUtils;
|
||||
import org.springframework.core.KotlinDetector;
|
||||
import org.springframework.core.MethodIntrospector;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
@@ -264,10 +268,18 @@ public final class HttpServiceProxyFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
Method method = invocation.getMethod();
|
||||
HttpServiceMethod httpServiceMethod = this.httpServiceMethods.get(method);
|
||||
if (httpServiceMethod != null) {
|
||||
if (KotlinDetector.isSuspendingFunction(method)) {
|
||||
Object[] arguments = getSuspendedFunctionArgs(invocation.getArguments());
|
||||
Continuation<Object> continuation = resolveContinuationArgument(invocation.getArguments());
|
||||
Mono<Object> wrapped = (Mono<Object>) httpServiceMethod.invoke(arguments);
|
||||
return CoroutinesUtils.awaitSingleOrNull(wrapped, continuation);
|
||||
}
|
||||
|
||||
return httpServiceMethod.invoke(invocation.getArguments());
|
||||
}
|
||||
if (method.isDefault()) {
|
||||
@@ -278,6 +290,17 @@ public final class HttpServiceProxyFactory {
|
||||
}
|
||||
throw new IllegalStateException("Unexpected method invocation: " + method);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private static <T> Continuation<T> resolveContinuationArgument(Object[] args) {
|
||||
return (Continuation<T>) args[args.length - 1];
|
||||
}
|
||||
|
||||
private static Object[] getSuspendedFunctionArgs(Object[] args) {
|
||||
Object[] functionArgs = new Object[args.length - 1];
|
||||
System.arraycopy(args, 0, functionArgs, 0, args.length - 1);
|
||||
return functionArgs;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user