Skip to content

Commit

Permalink
Add a classpath check for AOP Coroutines/Reactive conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
sdeleuze committed Apr 9, 2024
1 parent 7b7cfb2 commit 23696b7
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ class CglibAopProxy implements AopProxy, Serializable {

private static final String COROUTINES_FLOW_CLASS_NAME = "kotlinx.coroutines.flow.Flow";

private static final boolean coroutinesReactorPresent = ClassUtils.isPresent("kotlinx.coroutines.reactor.MonoKt",
CglibAopProxy.class.getClassLoader());;


/** The configuration used to configure this proxy. */
protected final AdvisedSupport advised;
Expand Down Expand Up @@ -421,7 +424,7 @@ private static Object processReturnType(
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
if (KotlinDetector.isSuspendingFunction(method)) {
if (coroutinesReactorPresent && KotlinDetector.isSuspendingFunction(method)) {
return COROUTINES_FLOW_CLASS_NAME.equals(new MethodParameter(method, -1).getParameterType().getName()) ?
CoroutinesUtils.asFlow(returnValue) :
CoroutinesUtils.awaitSingleOrNull(returnValue, arguments[arguments.length - 1]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa

private static final String COROUTINES_FLOW_CLASS_NAME = "kotlinx.coroutines.flow.Flow";

private static final boolean coroutinesReactorPresent = ClassUtils.isPresent("kotlinx.coroutines.reactor.MonoKt",
JdkDynamicAopProxy.class.getClassLoader());;

/** We use a static Log to avoid serialization issues. */
private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);

Expand Down Expand Up @@ -234,7 +237,7 @@ else if (retVal == null && returnType != void.class && returnType.isPrimitive())
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
if (KotlinDetector.isSuspendingFunction(method)) {
if (coroutinesReactorPresent && KotlinDetector.isSuspendingFunction(method)) {
return COROUTINES_FLOW_CLASS_NAME.equals(new MethodParameter(method, -1).getParameterType().getName()) ?
CoroutinesUtils.asFlow(retVal) : CoroutinesUtils.awaitSingleOrNull(retVal, args[args.length - 1]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import kotlin.coroutines.Continuation;
import kotlin.coroutines.CoroutineContext;
import kotlinx.coroutines.Job;
import org.reactivestreams.Publisher;

import org.springframework.aop.Advisor;
import org.springframework.aop.AopInvocationException;
Expand Down Expand Up @@ -65,6 +64,9 @@
*/
public abstract class AopUtils {

private static final boolean coroutinesReactorPresent = ClassUtils.isPresent("kotlinx.coroutines.reactor.MonoKt",
AopUtils.class.getClassLoader());;

/**
* Check whether the given object is a JDK dynamic proxy or a CGLIB proxy.
* <p>This method additionally checks if the given object is an instance
Expand Down Expand Up @@ -347,7 +349,7 @@ public static Object invokeJoinpointUsingReflection(@Nullable Object target, Met
// Use reflection to invoke the method.
try {
ReflectionUtils.makeAccessible(method);
return KotlinDetector.isSuspendingFunction(method) ?
return coroutinesReactorPresent && KotlinDetector.isSuspendingFunction(method) ?
KotlinDelegate.invokeSuspendingFunction(method, target, args) : method.invoke(target, args);
}
catch (InvocationTargetException ex) {
Expand All @@ -370,7 +372,7 @@ public static Object invokeJoinpointUsingReflection(@Nullable Object target, Met
*/
private static class KotlinDelegate {

public static Publisher<?> invokeSuspendingFunction(Method method, @Nullable Object target, Object... args) {
public static Object invokeSuspendingFunction(Method method, @Nullable Object target, Object... args) {
Continuation<?> continuation = (Continuation<?>) args[args.length -1];
Assert.state(continuation != null, "No Continuation available");
CoroutineContext context = continuation.getContext().minusKey(Job.Key);
Expand Down

0 comments on commit 23696b7

Please sign in to comment.