Skip to content

Commit 8999d6e

Browse files
Add some initial tests, fix @Raw annotation usage with reflection api
spotless
1 parent 307c7e0 commit 8999d6e

25 files changed

Lines changed: 727 additions & 70 deletions

File tree

client/src/main/java/dev/restate/client/Client.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import dev.restate.common.reflections.MethodInfo;
1818
import dev.restate.common.reflections.ProxySupport;
1919
import dev.restate.common.reflections.ReflectionUtils;
20-
import dev.restate.common.reflections.RestateUtils;
2120
import dev.restate.sdk.annotation.Service;
2221
import dev.restate.sdk.annotation.VirtualObject;
2322
import dev.restate.sdk.annotation.Workflow;
@@ -568,8 +567,8 @@ default <SVC> SVC service(Class<SVC> clazz) {
568567
return this.call(
569568
Request.of(
570569
Target.virtualObject(serviceName, null, methodInfo.getHandlerName()),
571-
(TypeTag<? super Object>) RestateUtils.typeTag(methodInfo.getInputType()),
572-
(TypeTag<? super Object>) RestateUtils.typeTag(methodInfo.getOutputType()),
570+
(TypeTag<? super Object>) methodInfo.getInputType(),
571+
(TypeTag<? super Object>) methodInfo.getOutputType(),
573572
invocation.getArguments().length == 0 ? null : invocation.getArguments()[0]))
574573
.response();
575574
});
@@ -647,8 +646,8 @@ default <SVC> SVC virtualObject(Class<SVC> clazz, String key) {
647646
return this.call(
648647
Request.of(
649648
Target.virtualObject(serviceName, key, methodInfo.getHandlerName()),
650-
(TypeTag<? super Object>) RestateUtils.typeTag(methodInfo.getInputType()),
651-
(TypeTag<? super Object>) RestateUtils.typeTag(methodInfo.getOutputType()),
649+
(TypeTag<? super Object>) methodInfo.getInputType(),
650+
(TypeTag<? super Object>) methodInfo.getOutputType(),
652651
invocation.getArguments().length == 0 ? null : invocation.getArguments()[0]))
653652
.response();
654653
});
@@ -727,8 +726,8 @@ default <SVC> SVC workflow(Class<SVC> clazz, String key) {
727726
return this.call(
728727
Request.of(
729728
Target.virtualObject(serviceName, key, methodInfo.getHandlerName()),
730-
(TypeTag<? super Object>) RestateUtils.typeTag(methodInfo.getInputType()),
731-
(TypeTag<? super Object>) RestateUtils.typeTag(methodInfo.getOutputType()),
729+
(TypeTag<? super Object>) methodInfo.getInputType(),
730+
(TypeTag<? super Object>) methodInfo.getOutputType(),
732731
invocation.getArguments().length == 0 ? null : invocation.getArguments()[0]))
733732
.response();
734733
});

client/src/main/java/dev/restate/client/ClientServiceHandleImpl.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ public <I, O> CompletableFuture<Response<O>> callAsync(
4949
serviceName,
5050
key,
5151
methodInfo.getHandlerName(),
52-
(TypeTag<I>) RestateUtils.typeTag(methodInfo.getInputType()),
53-
(TypeTag<O>) RestateUtils.typeTag(methodInfo.getOutputType()),
52+
(TypeTag<I>) methodInfo.getInputType(),
53+
(TypeTag<O>) methodInfo.getOutputType(),
5454
input,
5555
invocationOptions));
5656
}
@@ -65,7 +65,7 @@ public <I> CompletableFuture<Response<Void>> callAsync(
6565
serviceName,
6666
key,
6767
methodInfo.getHandlerName(),
68-
(TypeTag<I>) RestateUtils.typeTag(methodInfo.getInputType()),
68+
(TypeTag<I>) methodInfo.getInputType(),
6969
Serde.VOID,
7070
input,
7171
invocationOptions));
@@ -82,7 +82,7 @@ public <O> CompletableFuture<Response<O>> callAsync(
8282
key,
8383
methodInfo.getHandlerName(),
8484
Serde.VOID,
85-
(TypeTag<O>) RestateUtils.typeTag(methodInfo.getOutputType()),
85+
(TypeTag<O>) methodInfo.getOutputType(),
8686
null,
8787
invocationOptions));
8888
}
@@ -112,8 +112,8 @@ public <I, O> CompletableFuture<SendResponse<O>> sendAsync(
112112
serviceName,
113113
key,
114114
methodInfo.getHandlerName(),
115-
(TypeTag<I>) RestateUtils.typeTag(methodInfo.getInputType()),
116-
(TypeTag<O>) RestateUtils.typeTag(methodInfo.getOutputType()),
115+
(TypeTag<I>) methodInfo.getInputType(),
116+
(TypeTag<O>) methodInfo.getOutputType(),
117117
input,
118118
invocationOptions),
119119
delay);
@@ -129,7 +129,7 @@ public <I> CompletableFuture<SendResponse<Void>> sendAsync(
129129
serviceName,
130130
key,
131131
methodInfo.getHandlerName(),
132-
(TypeTag<I>) RestateUtils.typeTag(methodInfo.getInputType()),
132+
(TypeTag<I>) methodInfo.getInputType(),
133133
Serde.VOID,
134134
input,
135135
invocationOptions),
@@ -147,7 +147,7 @@ public <O> CompletableFuture<SendResponse<O>> sendAsync(
147147
key,
148148
methodInfo.getHandlerName(),
149149
Serde.VOID,
150-
(TypeTag<O>) RestateUtils.typeTag(methodInfo.getOutputType()),
150+
(TypeTag<O>) methodInfo.getOutputType(),
151151
null,
152152
invocationOptions),
153153
delay);

common/src/main/java/dev/restate/common/reflections/MethodInfo.java

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,19 @@
88
// https://github.com/restatedev/sdk-java/blob/main/LICENSE
99
package dev.restate.common.reflections;
1010

11+
import dev.restate.sdk.annotation.Raw;
12+
import dev.restate.serde.Serde;
13+
import dev.restate.serde.TypeTag;
1114
import java.lang.reflect.Method;
1215
import java.lang.reflect.Type;
16+
import org.jspecify.annotations.Nullable;
1317

1418
public class MethodInfo extends RuntimeException {
1519
private final String handlerName;
16-
private final Type inputType;
17-
private final Type outputType;
20+
private final TypeTag<?> inputType;
21+
private final TypeTag<?> outputType;
1822

19-
private MethodInfo(String handlerName, Type inputType, Type outputType) {
23+
private MethodInfo(String handlerName, TypeTag<?> inputType, TypeTag<?> outputType) {
2024
this.inputType = inputType;
2125
this.outputType = outputType;
2226
this.handlerName = handlerName;
@@ -26,21 +30,40 @@ public String getHandlerName() {
2630
return handlerName;
2731
}
2832

29-
public Type getInputType() {
33+
public TypeTag<? extends Object> getInputType() {
3034
return inputType;
3135
}
3236

33-
public Type getOutputType() {
37+
public TypeTag<? extends Object> getOutputType() {
3438
return outputType;
3539
}
3640

3741
public static MethodInfo fromMethod(Method method) {
3842
var handlerInfo = ReflectionUtils.mustHaveHandlerAnnotation(method);
3943
var genericParameters = method.getGenericParameterTypes();
40-
var inputType = genericParameters.length == 0 ? Void.TYPE : genericParameters[0];
41-
var outputType = method.getGenericReturnType();
4244
var handlerName = handlerInfo.name();
45+
TypeTag<?> inputTypeTag =
46+
genericParameters.length == 0
47+
? Serde.VOID
48+
: resolveTypeTag(
49+
genericParameters[0], method.getParameters()[0].getAnnotation(Raw.class));
50+
TypeTag<?> outputTypeTag =
51+
resolveTypeTag(method.getGenericReturnType(), method.getAnnotation(Raw.class));
4352

44-
return new MethodInfo(handlerName, inputType, outputType);
53+
return new MethodInfo(handlerName, inputTypeTag, outputTypeTag);
54+
}
55+
56+
private static TypeTag<?> resolveTypeTag(@Nullable Type type, @Nullable Raw rawAnnotation) {
57+
if (type == null) {
58+
return Serde.VOID;
59+
}
60+
61+
if (rawAnnotation != null && !rawAnnotation.contentType().equals("application/octet-stream")) {
62+
return Serde.withContentType(rawAnnotation.contentType(), Serde.RAW);
63+
} else if (rawAnnotation != null) {
64+
return Serde.RAW;
65+
} else {
66+
return RestateUtils.typeTag(type);
67+
}
4568
}
4669
}

common/src/main/java/dev/restate/common/reflections/MethodInfoCollector.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,39 +21,39 @@ public MethodInfoCollector(Class<SVC> svcClass) {
2121
this.infoCollectorProxy = ProxySupport.createProxy(svcClass, METHOD_INFO_COLLECTOR_INTERCEPTOR);
2222
}
2323

24-
public <O> MethodInfo resolve(Function<SVC, O> s) {
24+
public <O> MethodInfo resolve(Function<SVC, O> methodReference) {
2525
try {
26-
s.apply(this.infoCollectorProxy);
26+
methodReference.apply(this.infoCollectorProxy);
2727
throw new UnsupportedOperationException(
2828
"The provided lambda MUST contain ONLY a method reference to the service method");
2929
} catch (MethodInfo e) {
3030
return e;
3131
}
3232
}
3333

34-
public <I, O> MethodInfo resolve(BiFunction<SVC, I, O> s, I input) {
34+
public <I, O> MethodInfo resolve(BiFunction<SVC, I, O> methodReference, I input) {
3535
try {
36-
s.apply(this.infoCollectorProxy, input);
36+
methodReference.apply(this.infoCollectorProxy, input);
3737
throw new UnsupportedOperationException(
3838
"The provided lambda MUST contain ONLY a method reference to the service method");
3939
} catch (MethodInfo e) {
4040
return e;
4141
}
4242
}
4343

44-
public <I> MethodInfo resolve(BiConsumer<SVC, I> s, I input) {
44+
public <I> MethodInfo resolve(BiConsumer<SVC, I> methodReference, I input) {
4545
try {
46-
s.accept(this.infoCollectorProxy, input);
46+
methodReference.accept(this.infoCollectorProxy, input);
4747
throw new UnsupportedOperationException(
4848
"The provided lambda MUST contain ONLY a method reference to a service method");
4949
} catch (MethodInfo e) {
5050
return e;
5151
}
5252
}
5353

54-
public MethodInfo resolve(Consumer<SVC> s) {
54+
public MethodInfo resolve(Consumer<SVC> methodReference) {
5555
try {
56-
s.accept(this.infoCollectorProxy);
56+
methodReference.accept(this.infoCollectorProxy);
5757
throw new UnsupportedOperationException(
5858
"The provided lambda MUST contain ONLY a method reference to a service method");
5959
} catch (MethodInfo e) {

common/src/main/java/dev/restate/common/reflections/ReflectionUtils.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,15 +217,24 @@ public static HandlerInfo mustHaveHandlerAnnotation(@NonNull Method method) {
217217
// Check for @Handler or @Shared annotation (Shared implies Handler)
218218
var handlerAnnotation = findAnnotation(method, Handler.class);
219219
var sharedAnnotation = findAnnotation(method, Shared.class);
220+
var exclusiveAnnotation = findAnnotation(method, Exclusive.class);
221+
var workflowAnnotation = findAnnotation(method, Workflow.class);
220222

221-
if (handlerAnnotation == null && sharedAnnotation == null) {
223+
if (handlerAnnotation == null
224+
&& sharedAnnotation == null
225+
&& workflowAnnotation == null
226+
&& exclusiveAnnotation == null) {
222227
throw new IllegalArgumentException(
223228
"The invoked method '"
224229
+ method.getName()
225230
+ "' is not annotated with @"
226231
+ Handler.class.getSimpleName()
227232
+ " or @"
228-
+ Shared.class.getSimpleName());
233+
+ Shared.class.getSimpleName()
234+
+ " or @"
235+
+ Exclusive.class.getSimpleName()
236+
+ " or @"
237+
+ Workflow.class.getSimpleName());
229238
}
230239

231240
// Extract the name from @Name annotation, or default to method name

examples/src/main/java/my/restate/sdk/examples/LoanWorkflow.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
package my.restate.sdk.examples;
1010

1111
import dev.restate.client.Client;
12-
import dev.restate.client.ClientServiceReference;
1312
import dev.restate.sdk.*;
1413
import dev.restate.sdk.annotation.Handler;
1514
import dev.restate.sdk.annotation.Service;
@@ -143,13 +142,14 @@ public static void main(String[] args) {
143142

144143
// To invoke the workflow:
145144
Client restateClient = Client.connect("http://127.0.0.1:8080");
146-
LoanWorkflow loanWorkflow =
147-
restateClient.workflow(LoanWorkflow.class, "my-loan");
145+
LoanWorkflow loanWorkflow = restateClient.workflow(LoanWorkflow.class, "my-loan");
148146
var handle =
149-
restateClient.workflowHandle(LoanWorkflow.class, "my-loan").send(
150-
LoanWorkflow::run,
151-
new LoanRequest(
152-
"Francesco", "slinkydeveloper", "DE1234", new BigDecimal("1000000000")));
147+
restateClient
148+
.workflowHandle(LoanWorkflow.class, "my-loan")
149+
.send(
150+
LoanWorkflow::run,
151+
new LoanRequest(
152+
"Francesco", "slinkydeveloper", "DE1234", new BigDecimal("1000000000")));
153153

154154
LOG.info("Started loan workflow");
155155

sdk-api/src/main/java/dev/restate/sdk/Restate.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import dev.restate.common.reflections.MethodInfo;
1919
import dev.restate.common.reflections.ProxySupport;
2020
import dev.restate.common.reflections.ReflectionUtils;
21-
import dev.restate.common.reflections.RestateUtils;
2221
import dev.restate.sdk.annotation.Service;
2322
import dev.restate.sdk.annotation.VirtualObject;
2423
import dev.restate.sdk.annotation.Workflow;
@@ -443,8 +442,8 @@ public static <SVC> SVC service(Class<SVC> clazz) {
443442
.call(
444443
Request.of(
445444
Target.virtualObject(serviceName, null, methodInfo.getHandlerName()),
446-
(TypeTag<? super Object>) RestateUtils.typeTag(methodInfo.getInputType()),
447-
(TypeTag<? super Object>) RestateUtils.typeTag(methodInfo.getOutputType()),
445+
(TypeTag<? super Object>) methodInfo.getInputType(),
446+
(TypeTag<? super Object>) methodInfo.getOutputType(),
448447
invocation.getArguments().length == 0 ? null : invocation.getArguments()[0]))
449448
.await();
450449
});
@@ -519,8 +518,8 @@ public static <SVC> SVC virtualObject(Class<SVC> clazz, String key) {
519518
.call(
520519
Request.of(
521520
Target.virtualObject(serviceName, key, methodInfo.getHandlerName()),
522-
(TypeTag<? super Object>) RestateUtils.typeTag(methodInfo.getInputType()),
523-
(TypeTag<? super Object>) RestateUtils.typeTag(methodInfo.getOutputType()),
521+
(TypeTag<? super Object>) methodInfo.getInputType(),
522+
(TypeTag<? super Object>) methodInfo.getOutputType(),
524523
invocation.getArguments().length == 0 ? null : invocation.getArguments()[0]))
525524
.await();
526525
});
@@ -596,8 +595,8 @@ public static <SVC> SVC workflow(Class<SVC> clazz, String key) {
596595
.call(
597596
Request.of(
598597
Target.virtualObject(serviceName, key, methodInfo.getHandlerName()),
599-
(TypeTag<? super Object>) RestateUtils.typeTag(methodInfo.getInputType()),
600-
(TypeTag<? super Object>) RestateUtils.typeTag(methodInfo.getOutputType()),
598+
(TypeTag<? super Object>) methodInfo.getInputType(),
599+
(TypeTag<? super Object>) methodInfo.getOutputType(),
601600
invocation.getArguments().length == 0 ? null : invocation.getArguments()[0]))
602601
.await();
603602
});

sdk-api/src/main/java/dev/restate/sdk/ServiceHandleImpl.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ public <I, O> DurableFuture<O> call(
4747
serviceName,
4848
key,
4949
methodInfo.getHandlerName(),
50-
(TypeTag<I>) RestateUtils.typeTag(methodInfo.getInputType()),
51-
(TypeTag<O>) RestateUtils.typeTag(methodInfo.getOutputType()),
50+
(TypeTag<I>) methodInfo.getInputType(),
51+
(TypeTag<O>) methodInfo.getOutputType(),
5252
input,
5353
options));
5454
}
@@ -64,7 +64,7 @@ public <I> DurableFuture<Void> call(
6464
serviceName,
6565
key,
6666
methodInfo.getHandlerName(),
67-
(TypeTag<I>) RestateUtils.typeTag(methodInfo.getInputType()),
67+
(TypeTag<I>) methodInfo.getInputType(),
6868
Serde.VOID,
6969
input,
7070
options));
@@ -81,7 +81,7 @@ public <O> DurableFuture<O> call(Function<SVC, O> methodReference, InvocationOpt
8181
key,
8282
methodInfo.getHandlerName(),
8383
Serde.VOID,
84-
(TypeTag<O>) RestateUtils.typeTag(methodInfo.getOutputType()),
84+
(TypeTag<O>) methodInfo.getOutputType(),
8585
null,
8686
options));
8787
}
@@ -112,8 +112,8 @@ public <I, O> InvocationHandle<O> send(
112112
serviceName,
113113
key,
114114
methodInfo.getHandlerName(),
115-
(TypeTag<I>) RestateUtils.typeTag(methodInfo.getInputType()),
116-
(TypeTag<O>) RestateUtils.typeTag(methodInfo.getOutputType()),
115+
(TypeTag<I>) methodInfo.getInputType(),
116+
(TypeTag<O>) methodInfo.getOutputType(),
117117
input,
118118
options),
119119
delay);
@@ -130,7 +130,7 @@ public <I> InvocationHandle<Void> send(
130130
serviceName,
131131
key,
132132
methodInfo.getHandlerName(),
133-
(TypeTag<I>) RestateUtils.typeTag(methodInfo.getInputType()),
133+
(TypeTag<I>) methodInfo.getInputType(),
134134
Serde.VOID,
135135
input,
136136
options),
@@ -149,7 +149,7 @@ public <O> InvocationHandle<O> send(
149149
key,
150150
methodInfo.getHandlerName(),
151151
Serde.VOID,
152-
(TypeTag<O>) RestateUtils.typeTag(methodInfo.getOutputType()),
152+
(TypeTag<O>) methodInfo.getOutputType(),
153153
null,
154154
options),
155155
delay);

0 commit comments

Comments
 (0)