Skip to content

Commit 760cb7b

Browse files
Kotlin reflections support
1 parent d48e074 commit 760cb7b

File tree

31 files changed

+2365
-36
lines changed

31 files changed

+2365
-36
lines changed

bytebuddy-proxy-support/src/main/java/dev/restate/bytebuddy/proxysupport/ByteBuddyProxyFactory.java

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,24 @@ public final class ByteBuddyProxyFactory implements ProxyFactory {
5151
public <T> @Nullable T createProxy(Class<T> clazz, MethodInterceptor interceptor) {
5252
// Cannot proxy final classes
5353
if (Modifier.isFinal(clazz.getModifiers())) {
54-
throw new IllegalArgumentException("Class " + clazz + " is final, cannot be proxied.");
54+
if (ReflectionUtils.isKotlinClass(clazz)) {
55+
throw new IllegalArgumentException(
56+
clazz
57+
+
58+
"""
59+
is not open, cannot be proxied. Suggestions:
60+
* Extract the @Handler annotated functions in an interface
61+
* Make the class and all its @Handler annotated functions 'open'
62+
* Use the Kotlin allopen compiler plugin https://kotlinlang.org/docs/all-open-plugin.html with the following configuration:
63+
64+
allOpen {
65+
annotations("dev.restate.sdk.annotation.Service", "dev.restate.sdk.annotation.VirtualObject", "dev.restate.sdk.annotation.Workflow")
66+
}
67+
""");
68+
}
69+
throw new IllegalArgumentException(
70+
clazz
71+
+ " is final, cannot be proxied. Remove the final keyword, or refactor it extracting the restate interface out of it.");
5572
}
5673

5774
try {
@@ -87,7 +104,7 @@ public Method getMethod() {
87104

88105
return proxyInstance;
89106
} catch (Exception e) {
90-
throw new IllegalArgumentException("Cannot create proxy for class " + clazz, e);
107+
throw new IllegalArgumentException("Cannot create proxy for " + clazz, e);
91108
}
92109
}
93110

@@ -99,10 +116,11 @@ private <T> Class<?> generateProxyClass(Class<T> clazz) throws NoSuchFieldExcept
99116
ReflectionUtils.getUniqueDeclaredMethods(
100117
clazz,
101118
method ->
102-
ReflectionUtils.findAnnotation(method, Handler.class) != null
103-
|| ReflectionUtils.findAnnotation(method, Shared.class) != null
104-
|| ReflectionUtils.findAnnotation(method, Workflow.class) != null
105-
|| ReflectionUtils.findAnnotation(method, Exclusive.class) != null);
119+
!Modifier.isStatic(method.getModifiers())
120+
&& (ReflectionUtils.findAnnotation(method, Handler.class) != null
121+
|| ReflectionUtils.findAnnotation(method, Shared.class) != null
122+
|| ReflectionUtils.findAnnotation(method, Workflow.class) != null
123+
|| ReflectionUtils.findAnnotation(method, Exclusive.class) != null));
106124
for (var method : methods) {
107125
validateMethod(method);
108126
}
@@ -114,10 +132,12 @@ private <T> Class<?> generateProxyClass(Class<T> clazz) throws NoSuchFieldExcept
114132
: byteBuddy.subclass(clazz);
115133

116134
var annotationMatcher =
117-
isAnnotatedWith(Handler.class)
118-
.or(isAnnotatedWith(Exclusive.class))
119-
.or(isAnnotatedWith(Shared.class))
120-
.or(isAnnotatedWith(Workflow.class));
135+
not(isStatic())
136+
.and(
137+
isAnnotatedWith(Handler.class)
138+
.or(isAnnotatedWith(Exclusive.class))
139+
.or(isAnnotatedWith(Shared.class))
140+
.or(isAnnotatedWith(Workflow.class)));
121141
try (var unloaded =
122142
builder
123143
// Add a field to store the interceptor

client-kotlin/build.gradle.kts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,16 @@ plugins {
55

66
description = "Restate Client to interact with services from within other Kotlin applications"
77

8+
configurations.all {
9+
// Gonna conflict with sdk-serde-kotlinx
10+
exclude(group = "dev.restate", module = "sdk-serde-jackson")
11+
}
12+
813
dependencies {
9-
api(project(":client")) { exclude("dev.restate", "sdk-serde-jackson") }
14+
api(project(":client"))
1015
api(project(":sdk-serde-kotlinx"))
1116

17+
implementation(project(":common-kotlin"))
1218
implementation(libs.kotlinx.coroutines.core)
19+
implementation(kotlin("reflect"))
1320
}

0 commit comments

Comments
 (0)