Skip to content

Commit 43c5835

Browse files
Allow checked exceptions in annotated services (#407)
This contains a bytecode breaking change in Handler.of static methods, due to the changed type.
1 parent 069a162 commit 43c5835

File tree

6 files changed

+64
-17
lines changed

6 files changed

+64
-17
lines changed

sdk-api-gen/src/test/java/dev/restate/sdk/CodegenTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import dev.restate.sdk.core.ProtoUtils;
2020
import dev.restate.sdk.core.TestDefinitions;
2121
import dev.restate.sdk.core.TestDefinitions.TestSuite;
22+
import java.io.IOException;
2223
import java.nio.charset.StandardCharsets;
2324
import java.util.stream.Stream;
2425

@@ -182,6 +183,14 @@ public String sharedHandler(SharedWorkflowContext context, String myInput) {
182183
}
183184
}
184185

186+
@Service
187+
static class CheckedException {
188+
@Handler
189+
String greet(Context context, String request) throws IOException {
190+
return request;
191+
}
192+
}
193+
185194
@Override
186195
public Stream<TestDefinitions.TestDefinition> definitions() {
187196
return Stream.of(

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

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,31 @@
99
package dev.restate.sdk;
1010

1111
import dev.restate.sdk.common.TerminalException;
12+
import dev.restate.sdk.common.function.ThrowingBiConsumer;
13+
import dev.restate.sdk.common.function.ThrowingBiFunction;
14+
import dev.restate.sdk.common.function.ThrowingConsumer;
15+
import dev.restate.sdk.common.function.ThrowingFunction;
1216
import dev.restate.sdk.common.syscalls.HandlerSpecification;
1317
import dev.restate.sdk.common.syscalls.SyscallCallback;
1418
import dev.restate.sdk.common.syscalls.Syscalls;
1519
import io.opentelemetry.context.Scope;
1620
import java.nio.ByteBuffer;
1721
import java.util.concurrent.Executor;
1822
import java.util.concurrent.Executors;
19-
import java.util.function.BiConsumer;
20-
import java.util.function.BiFunction;
21-
import java.util.function.Consumer;
22-
import java.util.function.Function;
2323
import org.apache.logging.log4j.LogManager;
2424
import org.apache.logging.log4j.Logger;
2525
import org.jspecify.annotations.Nullable;
2626

2727
/** Adapter class for {@link dev.restate.sdk.common.syscalls.HandlerRunner} to use the Java API. */
2828
public class HandlerRunner<REQ, RES>
2929
implements dev.restate.sdk.common.syscalls.HandlerRunner<REQ, RES, HandlerRunner.Options> {
30-
private final BiFunction<Context, REQ, RES> runner;
30+
private final ThrowingBiFunction<Context, REQ, RES> runner;
3131

3232
private static final Logger LOG = LogManager.getLogger(HandlerRunner.class);
3333

34-
HandlerRunner(BiFunction<? extends Context, REQ, RES> runner) {
34+
HandlerRunner(ThrowingBiFunction<? extends Context, REQ, RES> runner) {
3535
//noinspection unchecked
36-
this.runner = (BiFunction<Context, REQ, RES>) runner;
36+
this.runner = (ThrowingBiFunction<Context, REQ, RES>) runner;
3737
}
3838

3939
@Override
@@ -106,18 +106,19 @@ public void run(
106106
}
107107

108108
public static <CTX extends Context, REQ, RES> HandlerRunner<REQ, RES> of(
109-
BiFunction<CTX, REQ, RES> runner) {
109+
ThrowingBiFunction<CTX, REQ, RES> runner) {
110110
return new HandlerRunner<>(runner);
111111
}
112112

113113
@SuppressWarnings("unchecked")
114-
public static <CTX extends Context, RES> HandlerRunner<Void, RES> of(Function<CTX, RES> runner) {
114+
public static <CTX extends Context, RES> HandlerRunner<Void, RES> of(
115+
ThrowingFunction<CTX, RES> runner) {
115116
return new HandlerRunner<>((context, o) -> runner.apply((CTX) context));
116117
}
117118

118119
@SuppressWarnings("unchecked")
119120
public static <CTX extends Context, REQ> HandlerRunner<REQ, Void> of(
120-
BiConsumer<CTX, REQ> runner) {
121+
ThrowingBiConsumer<CTX, REQ> runner) {
121122
return new HandlerRunner<>(
122123
(context, o) -> {
123124
runner.accept((CTX) context, o);
@@ -126,7 +127,7 @@ public static <CTX extends Context, REQ> HandlerRunner<REQ, Void> of(
126127
}
127128

128129
@SuppressWarnings("unchecked")
129-
public static <CTX extends Context> HandlerRunner<Void, Void> of(Consumer<CTX> runner) {
130+
public static <CTX extends Context> HandlerRunner<Void, Void> of(ThrowingConsumer<CTX> runner) {
130131
return new HandlerRunner<>(
131132
(ctx, o) -> {
132133
runner.accept((CTX) ctx);

sdk-api/src/test/java/dev/restate/sdk/JavaBlockingTests.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import dev.restate.sdk.common.HandlerType;
1414
import dev.restate.sdk.common.Serde;
1515
import dev.restate.sdk.common.ServiceType;
16+
import dev.restate.sdk.common.function.ThrowingBiFunction;
1617
import dev.restate.sdk.common.syscalls.HandlerDefinition;
1718
import dev.restate.sdk.common.syscalls.HandlerSpecification;
1819
import dev.restate.sdk.common.syscalls.ServiceDefinition;
@@ -24,7 +25,6 @@
2425
import dev.restate.sdk.core.TestDefinitions.TestSuite;
2526
import dev.restate.sdk.core.TestRunner;
2627
import java.util.List;
27-
import java.util.function.BiFunction;
2828
import java.util.stream.Stream;
2929

3030
public class JavaBlockingTests extends TestRunner {
@@ -52,7 +52,7 @@ public Stream<TestSuite> definitions() {
5252
}
5353

5454
public static <T, R> TestInvocationBuilder testDefinitionForService(
55-
String name, Serde<T> reqSerde, Serde<R> resSerde, BiFunction<Context, T, R> runner) {
55+
String name, Serde<T> reqSerde, Serde<R> resSerde, ThrowingBiFunction<Context, T, R> runner) {
5656
return TestDefinitions.testInvocation(
5757
ServiceDefinition.of(
5858
name,
@@ -65,7 +65,10 @@ public static <T, R> TestInvocationBuilder testDefinitionForService(
6565
}
6666

6767
public static <T, R> TestInvocationBuilder testDefinitionForVirtualObject(
68-
String name, Serde<T> reqSerde, Serde<R> resSerde, BiFunction<ObjectContext, T, R> runner) {
68+
String name,
69+
Serde<T> reqSerde,
70+
Serde<R> resSerde,
71+
ThrowingBiFunction<ObjectContext, T, R> runner) {
6972
return TestDefinitions.testInvocation(
7073
ServiceDefinition.of(
7174
name,
@@ -78,7 +81,10 @@ public static <T, R> TestInvocationBuilder testDefinitionForVirtualObject(
7881
}
7982

8083
public static <T, R> TestInvocationBuilder testDefinitionForWorkflow(
81-
String name, Serde<T> reqSerde, Serde<R> resSerde, BiFunction<WorkflowContext, T, R> runner) {
84+
String name,
85+
Serde<T> reqSerde,
86+
Serde<R> resSerde,
87+
ThrowingBiFunction<WorkflowContext, T, R> runner) {
8288
return TestDefinitions.testInvocation(
8389
ServiceDefinition.of(
8490
name,

sdk-api/src/test/java/dev/restate/sdk/SideEffectTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,7 @@ protected TestInvocationBuilder failingSideEffectWithRetryPolicy(
117117
Serde.VOID,
118118
JsonSerdes.STRING,
119119
(ctx, unused) -> {
120-
PreviewContext.run(
121-
ctx,
120+
ctx.run(
122121
retryPolicy,
123122
() -> {
124123
throw new IllegalStateException(reason);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) 2023 - Restate Software, Inc., Restate GmbH
2+
//
3+
// This file is part of the Restate Java SDK,
4+
// which is released under the MIT license.
5+
//
6+
// You can find a copy of the license in file LICENSE in the root
7+
// directory of this repository or package, or at
8+
// https://github.com/restatedev/sdk-java/blob/main/LICENSE
9+
package dev.restate.sdk.common.function;
10+
11+
/** Like {@link java.util.function.BiFunction} but can throw checked exceptions. */
12+
@FunctionalInterface
13+
public interface ThrowingBiFunction<T, U, R> {
14+
R apply(T var1, U var2) throws Throwable;
15+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) 2023 - Restate Software, Inc., Restate GmbH
2+
//
3+
// This file is part of the Restate Java SDK,
4+
// which is released under the MIT license.
5+
//
6+
// You can find a copy of the license in file LICENSE in the root
7+
// directory of this repository or package, or at
8+
// https://github.com/restatedev/sdk-java/blob/main/LICENSE
9+
package dev.restate.sdk.common.function;
10+
11+
import java.util.function.Consumer;
12+
13+
/** Like {@link Consumer} but can throw checked exceptions. */
14+
@FunctionalInterface
15+
public interface ThrowingConsumer<T> {
16+
void accept(T var1) throws Throwable;
17+
}

0 commit comments

Comments
 (0)