Move Kotlin value class unboxing to InvocableHandlerMethod
Before this commit, in Spring Framework 6.2, Kotlin value class unboxing was done at CoroutinesUtils level, which is a good fit for InvocableHandlerMethod use case, but not for other ones like AopUtils. This commit moves such unboxing to InvocableHandlerMethod in order to keep the HTTP response body support while fixing other regressions. Closes gh-33943
This commit is contained in:
@@ -30,6 +30,8 @@ import kotlin.reflect.KType;
|
||||
import kotlin.reflect.full.KClasses;
|
||||
import kotlin.reflect.jvm.KCallablesJvm;
|
||||
import kotlin.reflect.jvm.ReflectJvmMapping;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.publisher.SynchronousSink;
|
||||
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.core.CoroutinesUtils;
|
||||
@@ -288,7 +290,8 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
* @since 6.0
|
||||
*/
|
||||
protected Object invokeSuspendingFunction(Method method, Object target, Object[] args) {
|
||||
return CoroutinesUtils.invokeSuspendingFunction(method, target, args);
|
||||
Object result = CoroutinesUtils.invokeSuspendingFunction(method, target, args);
|
||||
return (result instanceof Mono<?> mono ? mono.handle(KotlinDelegate::handleResult) : result);
|
||||
}
|
||||
|
||||
|
||||
@@ -298,7 +301,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
private static class KotlinDelegate {
|
||||
|
||||
@Nullable
|
||||
@SuppressWarnings({"deprecation", "DataFlowIssue"})
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
public static Object invokeFunction(Method method, Object target, Object[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
|
||||
KFunction<?> function = ReflectJvmMapping.getKotlinFunction(method);
|
||||
// For property accessors
|
||||
@@ -333,10 +336,33 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
}
|
||||
Object result = function.callBy(argMap);
|
||||
if (result != null && KotlinDetector.isInlineClass(result.getClass())) {
|
||||
return result.getClass().getDeclaredMethod("unbox-impl").invoke(result);
|
||||
result = unbox(result);
|
||||
}
|
||||
return (result == Unit.INSTANCE ? null : result);
|
||||
}
|
||||
|
||||
private static void handleResult(Object result, SynchronousSink<Object> sink) {
|
||||
if (KotlinDetector.isInlineClass(result.getClass())) {
|
||||
try {
|
||||
Object unboxed = unbox(result);
|
||||
if (unboxed != Unit.INSTANCE) {
|
||||
sink.next(unboxed);
|
||||
}
|
||||
sink.complete();
|
||||
}
|
||||
catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
|
||||
sink.error(ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
sink.next(result);
|
||||
sink.complete();
|
||||
}
|
||||
}
|
||||
|
||||
private static Object unbox(Object result) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
|
||||
return result.getClass().getDeclaredMethod("unbox-impl").invoke(result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user