99package dev.restate.sdk.kotlin.internal
1010
1111import dev.restate.common.reflections.ReflectionUtils
12- import dev.restate.sdk.annotation.Accept
13- import dev.restate.sdk.annotation.CustomSerdeFactory
14- import dev.restate.sdk.annotation.Exclusive
15- import dev.restate.sdk.annotation.Handler
16- import dev.restate.sdk.annotation.Json
17- import dev.restate.sdk.annotation.Raw
18- import dev.restate.sdk.annotation.Shared
19- import dev.restate.sdk.annotation.Workflow
20- import dev.restate.sdk.endpoint.definition.HandlerDefinition
12+ import dev.restate.sdk.annotation.*
13+ import dev.restate.sdk.endpoint.definition.*
2114import dev.restate.sdk.endpoint.definition.HandlerRunner
22- import dev.restate.sdk.endpoint.definition.HandlerType
23- import dev.restate.sdk.endpoint.definition.ServiceDefinition
24- import dev.restate.sdk.endpoint.definition.ServiceDefinitionFactory
25- import dev.restate.sdk.endpoint.definition.ServiceType
26- import dev.restate.sdk.kotlin.Context
27- import dev.restate.sdk.kotlin.ObjectContext
28- import dev.restate.sdk.kotlin.SharedObjectContext
29- import dev.restate.sdk.kotlin.SharedWorkflowContext
30- import dev.restate.sdk.kotlin.WorkflowContext
15+ import dev.restate.sdk.kotlin.*
3116import dev.restate.serde.Serde
3217import dev.restate.serde.SerdeFactory
3318import dev.restate.serde.kotlinx.KotlinSerializationSerdeFactory
3419import dev.restate.serde.kotlinx.KotlinSerializationSerdeFactory.KtTypeTag
3520import dev.restate.serde.provider.DefaultSerdeFactoryProvider
3621import java.lang.reflect.Modifier
3722import java.util.*
23+ import kotlin.reflect.KClass
3824import kotlin.reflect.KFunction
3925import kotlin.reflect.KVisibility
4026import kotlin.reflect.full.callSuspend
4127import kotlin.reflect.full.findAnnotation
28+ import kotlin.reflect.full.hasAnnotation
4229import kotlin.reflect.full.memberFunctions
4330import kotlin.reflect.full.valueParameters
4431import kotlin.reflect.jvm.javaMethod
@@ -66,15 +53,23 @@ internal class ReflectionServiceDefinitionFactory : ServiceDefinitionFactory<Any
6653
6754 val serviceClazz: Class <* > = serviceInstance.javaClass
6855
69- val hasServiceAnnotation = ReflectionUtils .hasServiceAnnotation(serviceClazz)
70- val hasVirtualObjectAnnotation = ReflectionUtils .hasVirtualObjectAnnotation(serviceClazz)
71- val hasWorkflowAnnotation = ReflectionUtils .hasWorkflowAnnotation(serviceClazz)
56+ // The behavior of the reflections work as follows:
57+ // * There is one class that has all the restate annotations. That being either the serviceClazz
58+ // itself (concrete class) or some interface in the hierarchy.
59+ // * Then there is the serviceInstance, which is where we call the methods themselves.
60+ val restateAnnotatedClazz = ReflectionUtils .findRestateAnnotatedClass(serviceClazz)
61+ val restateAnnotatedKotlinClazz = restateAnnotatedClazz.kotlin
62+
63+ val hasServiceAnnotation = ReflectionUtils .hasServiceAnnotation(restateAnnotatedClazz)
64+ val hasVirtualObjectAnnotation =
65+ ReflectionUtils .hasVirtualObjectAnnotation(restateAnnotatedClazz)
66+ val hasWorkflowAnnotation = ReflectionUtils .hasWorkflowAnnotation(restateAnnotatedClazz)
7267
7368 val hasAnyAnnotation =
7469 hasServiceAnnotation || hasVirtualObjectAnnotation || hasWorkflowAnnotation
7570 if (! hasAnyAnnotation) {
7671 throw MalformedRestateServiceException (
77- serviceClazz .simpleName,
72+ restateAnnotatedClazz .simpleName,
7873 " A restate component MUST be annotated with " +
7974 " exactly one annotation between @Service/@VirtualObject/@Workflow, no annotation was found" ,
8075 )
@@ -84,27 +79,24 @@ internal class ReflectionServiceDefinitionFactory : ServiceDefinitionFactory<Any
8479
8580 if (! hasExactlyOneAnnotation) {
8681 throw MalformedRestateServiceException (
87- serviceClazz .simpleName,
82+ restateAnnotatedClazz .simpleName,
8883 " A restate component MUST be annotated with " +
8984 " exactly one annotation between @Service/@VirtualObject/@Workflow, more than one annotation found" ,
9085 )
9186 }
9287
93- val serviceName = ReflectionUtils .extractServiceName(serviceClazz )
88+ val serviceName = ReflectionUtils .extractServiceName(restateAnnotatedClazz )
9489 val serviceType =
9590 if (hasServiceAnnotation) ServiceType .SERVICE
9691 else if (hasVirtualObjectAnnotation) ServiceType .VIRTUAL_OBJECT else ServiceType .WORKFLOW
97- val serdeFactory: SerdeFactory = resolveSerdeFactory(serviceClazz )
92+ val serdeFactory: SerdeFactory = resolveSerdeFactory(restateAnnotatedKotlinClazz )
9893
9994 val kFunctions =
100- serviceClazz.kotlin.memberFunctions.filter {
101- it.javaMethod?.let { method ->
102- // Can't use findAnnotations because that won't walk the stack!
103- ReflectionUtils .findAnnotation(method, Handler ::class .java) != null ||
104- ReflectionUtils .findAnnotation(method, Shared ::class .java) != null ||
105- ReflectionUtils .findAnnotation(method, Workflow ::class .java) != null ||
106- ReflectionUtils .findAnnotation(method, Exclusive ::class .java) != null
107- } ? : false
95+ restateAnnotatedKotlinClazz.memberFunctions.filter {
96+ it.hasAnnotation<Handler >() ||
97+ it.hasAnnotation<Shared >() ||
98+ it.hasAnnotation<Workflow >() ||
99+ it.hasAnnotation<Exclusive >()
108100 }
109101
110102 if (kFunctions.isEmpty()) {
@@ -351,20 +343,16 @@ internal class ReflectionServiceDefinitionFactory : ServiceDefinitionFactory<Any
351343 return serde
352344 }
353345
354- private fun resolveSerdeFactory (serviceClazz : Class <* >): SerdeFactory {
346+ private fun resolveSerdeFactory (serviceClazz : KClass <* >): SerdeFactory {
355347 // Check for CustomSerdeFactory annotation
356- val customSerdeFactoryAnnotation: CustomSerdeFactory ? =
357- ReflectionUtils .findAnnotation(
358- serviceClazz,
359- CustomSerdeFactory ::class .java,
360- )
348+ val customSerdeFactoryAnnotation = serviceClazz.findAnnotation<CustomSerdeFactory >()
361349
362350 if (customSerdeFactoryAnnotation != null ) {
363351 try {
364352 return customSerdeFactoryAnnotation.value.java.getDeclaredConstructor().newInstance()
365353 } catch (e: Exception ) {
366354 throw MalformedRestateServiceException (
367- serviceClazz.simpleName,
355+ serviceClazz.simpleName!! ,
368356 " Failed to instantiate custom SerdeFactory: ${customSerdeFactoryAnnotation.value.java.name} " ,
369357 e,
370358 )
@@ -392,7 +380,7 @@ internal class ReflectionServiceDefinitionFactory : ServiceDefinitionFactory<Any
392380 return this .cachedDefaultSerdeFactory!!
393381 } catch (e: Exception ) {
394382 throw MalformedRestateServiceException (
395- serviceClazz.simpleName,
383+ serviceClazz.simpleName!! ,
396384 " Failed to load KotlinSerializationSerdeFactory for Kotlin service. " +
397385 " Make sure sdk-serde-kotlinx is on the classpath." ,
398386 e,
0 commit comments