Skip to content

Commit

Permalink
Support Kotlin value classes as suspending function arguments
Browse files Browse the repository at this point in the history
Similar to spring-projectsgh-31698 but for Coroutines.

See spring-projectsgh-31846
  • Loading branch information
T45K authored and sdeleuze committed Dec 15, 2023
1 parent 503ccb5 commit bf08193
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.Objects;

Expand All @@ -40,6 +41,7 @@
import kotlinx.coroutines.reactor.MonoKt;
import kotlinx.coroutines.reactor.ReactorFlowKt;
import org.reactivestreams.Publisher;
import org.springframework.util.ReflectionUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

Expand All @@ -55,6 +57,9 @@
*/
public abstract class CoroutinesUtils {

private static final ReflectionUtils.MethodFilter boxImplFilter =
(method -> method.isSynthetic() && Modifier.isStatic(method.getModifiers()) && method.getName().equals("box-impl"));

/**
* Convert a {@link Deferred} instance to a {@link Mono}.
*/
Expand Down Expand Up @@ -115,7 +120,14 @@ public static Publisher<?> invokeSuspendingFunction(CoroutineContext context, Me
case INSTANCE -> argMap.put(parameter, target);
case VALUE -> {
if (!parameter.isOptional() || args[index] != null) {
argMap.put(parameter, args[index]);
if (parameter.getType().getClassifier() instanceof KClass<?> kClass && kClass.isValue()) {
Class<?> javaClass = JvmClassMappingKt.getJavaClass(kClass);
Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(javaClass, boxImplFilter);
Assert.state(methods.length == 1, "Unable to find a single box-impl synthetic static method in " + javaClass.getName());
argMap.put(parameter, ReflectionUtils.invokeMethod(methods[0], null, args[index]));
} else {
argMap.put(parameter, args[index]);
}
}
index++;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ class CoroutinesUtilsTests {
}
}

@Test
fun invokeSuspendingFunctionWithValueClassParameter() {
val method = CoroutinesUtilsTests::class.java.declaredMethods.first { it.name.startsWith("suspendingFunctionWithValueClass") }
val mono = CoroutinesUtils.invokeSuspendingFunction(method, this, "foo", null) as Mono
runBlocking {
Assertions.assertThat(mono.awaitSingle()).isEqualTo("foo")
}
}

suspend fun suspendingFunction(value: String): String {
delay(1)
return value
Expand Down Expand Up @@ -172,4 +181,12 @@ class CoroutinesUtilsTests {
return null
}

suspend fun suspendingFunctionWithValueClass(value: ValueClass): String {
delay(1)
return value.value
}

@JvmInline
value class ValueClass(val value: String)

}

0 comments on commit bf08193

Please sign in to comment.