Skip to content

Commit 3205fee

Browse files
Update readme (#271)
1 parent cd0007b commit 3205fee

File tree

1 file changed

+54
-167
lines changed

1 file changed

+54
-167
lines changed

README.md

Lines changed: 54 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ This SDK features:
1313
- Implement Restate services using either:
1414
- Java
1515
- Kotlin coroutines
16-
- Reuse the existing gRPC/Protobuf ecosystem to define service interfaces
1716
- Deploy Restate services as:
1817
- Non-blocking HTTP servers
1918
- On AWS Lambda
@@ -40,55 +39,13 @@ Scaffold a project using the build tool of your choice. For example, with Gradle
4039
gradle init --type java-application
4140
```
4241

43-
Add the dependency [sdk-api](sdk-api):
42+
Add the runtime dependency [sdk-api](sdk-api) and the annotation processor dependency [sdk-api-gen](sdk-api-gen):
4443

4544
```
46-
implementation("dev.restate:sdk-api:0.6.0")
45+
annotationProcessor("dev.restate:sdk-api-gen:0.9.0")
46+
implementation("dev.restate:sdk-api:0.9.0")
4747
```
4848

49-
Now you need to configure the protobuf plugin to build your Protobuf contracts. For example, with Gradle (Kotlin script):
50-
51-
```kts
52-
import com.google.protobuf.gradle.id
53-
54-
plugins {
55-
// ...
56-
id("com.google.protobuf") version "0.9.1"
57-
// ...
58-
}
59-
60-
dependencies {
61-
// ...
62-
// You need the following dependencies to compile the generated code
63-
implementation("com.google.protobuf:protobuf-java:3.24.3")
64-
implementation("io.grpc:grpc-stub:1.58.0")
65-
implementation("io.grpc:grpc-protobuf:1.58.0")
66-
compileOnly("org.apache.tomcat:annotations-api:6.0.53")
67-
}
68-
69-
// Configure protoc plugin
70-
protobuf {
71-
protoc { artifact = "com.google.protobuf:protoc:3.24.3" }
72-
73-
plugins {
74-
// The Restate plugin depends on the gRPC generated code
75-
id("grpc") { artifact = "io.grpc:protoc-gen-grpc-java:1.58.0" }
76-
id("restate") { artifact = "dev.restate:protoc-gen-restate:0.6.0:all@jar" }
77-
}
78-
79-
generateProtoTasks {
80-
all().forEach {
81-
it.plugins {
82-
id("grpc")
83-
id("restate")
84-
}
85-
}
86-
}
87-
}
88-
```
89-
90-
For Maven you can use the [xolstice Protobuf plugin](https://www.xolstice.org/protobuf-maven-plugin/index.html).
91-
9249
### Setup a project (Kotlin)
9350

9451
Scaffold a project using the build tool of your choice. For example, with Gradle (Kotlin script):
@@ -97,149 +54,101 @@ Scaffold a project using the build tool of your choice. For example, with Gradle
9754
gradle init --type kotlin-application
9855
```
9956

100-
Add the dependency [`sdk-api-kotlin`](sdk-api-kotlin):
57+
Add the [Kotlin symbol processing](https://kotlinlang.org/docs/ksp-quickstart.html#use-your-own-processor-in-a-project) plugin:
10158

10259
```
103-
implementation("dev.restate:sdk-api-kotlin:0.6.0")
104-
```
105-
106-
Now you need to configure the protobuf plugin to build your Protobuf contracts. For example, with Gradle (Kotlin script):
107-
108-
```kts
109-
import com.google.protobuf.gradle.id
110-
11160
plugins {
112-
// ...
113-
id("com.google.protobuf") version "0.9.1"
114-
// ...
115-
}
116-
117-
dependencies {
118-
// ...
119-
// You need the following dependencies to compile the generated code
120-
implementation("com.google.protobuf:protobuf-java:3.24.3")
121-
implementation("com.google.protobuf:protobuf-kotlin:3.24.3")
122-
implementation("io.grpc:grpc-stub:1.58.0")
123-
implementation("io.grpc:grpc-protobuf:1.58.0")
124-
implementation("io.grpc:grpc-kotlin-stub:1.4.0") { exclude("javax.annotation", "javax.annotation-api") }
125-
compileOnly("org.apache.tomcat:annotations-api:6.0.53")
126-
}
127-
128-
// Configure protoc plugin
129-
protobuf {
130-
protoc { artifact = "com.google.protobuf:protoc:3.24.3" }
131-
132-
plugins {
133-
// The gRPC Kotlin plugin depends on the gRPC generated code
134-
id("grpc") { artifact = "io.grpc:protoc-gen-grpc-java:1.58.0" }
135-
id("restate") { artifact = "dev.restate:protoc-gen-restate:0.6.0:all@jar" }
136-
}
137-
138-
generateProtoTasks {
139-
all().forEach {
140-
it.plugins {
141-
id("grpc")
142-
id("restate") {
143-
option("kotlin")
144-
}
145-
}
146-
it.builtins {
147-
// The Kotlin codegen depends on the Java generated code
148-
java {}
149-
id("kotlin")
150-
}
151-
}
152-
}
61+
id("com.google.devtools.ksp") version "1.9.22-1.0.18"
15362
}
15463
```
15564

156-
### Add the Protobuf contract
157-
158-
Now you can add the Protobuf contract under `src/main/proto`. For example:
159-
160-
```protobuf
161-
syntax = "proto3";
162-
package greeter;
65+
Add the runtime dependency [sdk-api-kotlin](sdk-api-kotlin) and the ksp dependency [sdk-api-gen](sdk-api-kotlin-gen):
16366

164-
option java_package = "my.greeter";
165-
option java_outer_classname = "GreeterProto";
166-
167-
import "dev/restate/ext.proto";
168-
169-
service Greeter {
170-
option (dev.restate.ext.service_type) = KEYED;
171-
172-
rpc Greet (GreetRequest) returns (GreetResponse);
173-
}
174-
175-
message GreetRequest {
176-
string name = 1 [(dev.restate.ext.field) = KEY];
177-
}
178-
179-
message GreetResponse {
180-
string message = 1;
181-
}
67+
```
68+
ksp("dev.restate:sdk-api-kotlin-gen:0.9.0")
69+
implementation("dev.restate:sdk-api-kotlin:0.9.0")
18270
```
18371

184-
By using the Gradle or Maven plugin, the code is automatically re-generated on every build.
185-
186-
### Implement the service (Java)
72+
### Implement your first Restate component (Java)
18773

188-
Implement the service in a new class, for example:
74+
Implement your first virtual object in a new class, for example:
18975

19076
```java
191-
public class Greeter extends GreeterRestate.GreeterRestateImplBase {
77+
import dev.restate.sdk.ObjectContext;
78+
import dev.restate.sdk.annotation.Handler;
79+
import dev.restate.sdk.annotation.VirtualObject;
80+
import dev.restate.sdk.common.CoreSerdes;
81+
import dev.restate.sdk.common.StateKey;
82+
83+
@VirtualObject
84+
public class Greeter {
19285

19386
private static final StateKey<Long> COUNT = StateKey.of("total", CoreSerdes.LONG);
19487

195-
@Override
196-
public GreetResponse greet(RestateContext ctx, GreetRequest request) {
88+
@Handler
89+
public String greet(ObjectContext ctx, String name) {
19790
long count = ctx.get(COUNT).orElse(0L);
19891
ctx.set(COUNT, count + 1);
19992

200-
return GreetResponse.newBuilder()
201-
.setMessage(String.format("Hello %s for the %d time!", request.getName(), count))
202-
.build();
93+
return String.format("Hello %s for the %d time!", name, count);
20394
}
20495
}
20596
```
20697

207-
If you want to use POJOs for state, check [how to use Jackson](#state-serde-using-jackson).
98+
When using composite types/POJOs for input/output, [Jackson Databind](https://github.com/FasterXML/jackson) will be used. The Jackson dependency is not automatically included, you must add it with [`sdk-serde-jackson`](sdk-serde-jackson):
20899

209-
### Implement the service (Kotlin)
100+
```
101+
implementation("dev.restate:sdk-serde-jackson:0.9.0")
102+
```
210103

211-
Implement the service in a new class, for example:
104+
If you want to store types/POJOs in state, use `JacksonSerdes`:
105+
106+
```java
107+
private static final StateKey<Person> PERSON = StateKey.of("person", JacksonSerdes.of(Person.class));
108+
```
109+
110+
### Implement your first Restate component (Kotlin)
111+
112+
Implement your first virtual object in a new class, for example:
212113

213114
```kotlin
214-
class Greeter : GreeterRestateKtImplBase() {
115+
import dev.restate.sdk.annotation.Handler
116+
import dev.restate.sdk.annotation.VirtualObject
117+
import dev.restate.sdk.common.StateKey
118+
import dev.restate.sdk.kotlin.KtSerdes
119+
import dev.restate.sdk.kotlin.ObjectContext
120+
121+
@VirtualObject
122+
class Greeter {
215123
companion object {
216-
private val COUNT = StateKey.of("total", CoreSerdes.LONG)
124+
private val COUNT = StateKey.of<Long>("total", KtSerdes.json())
217125
}
218126

219-
override suspend fun greet(context: RestateContext, request: GreetRequest): GreetResponse {
127+
@Handler
128+
suspend fun greet(context: ObjectContext, name: String): String {
220129
val count = context.get(COUNT) ?: 0L
221130
context.set(COUNT, count + 1)
222-
return greetResponse { message = "Hello ${request.name} for the $count time!" }
131+
return "Hello $name for the $count time!"
223132
}
224133
}
225134
```
226135

227-
If you want to use POJOs for state, check [how to use Jackson](#state-serde-using-jackson).
136+
When using composite data types for input/output, [`kotlinx.serialization`](https://github.com/Kotlin/kotlinx.serialization?tab=readme-ov-file#setup) will be used.
228137

229138
### Deploy the service (HTTP Server)
230139

231140
To deploy the Restate service as HTTP server, add [`sdk-http-vertx`](sdk-http-vertx) to the dependencies. For example, in Gradle:
232141

233142
```
234-
implementation("dev.restate:sdk-http-vertx:0.6.0")
143+
implementation("dev.restate:sdk-http-vertx:0.9.0")
235144
```
236145

237146
To deploy the service, add the following code to the `main`. For example in Java:
238147

239148
```java
240149
public static void main(String[] args) {
241150
RestateHttpEndpointBuilder.builder()
242-
.withService(new Greeter())
151+
.bind(new Greeter())
243152
.buildAndListen();
244153
}
245154
```
@@ -249,7 +158,7 @@ In Kotlin:
249158
```kotlin
250159
fun main() {
251160
RestateHttpEndpointBuilder.builder()
252-
.withService(Greeter())
161+
.bind(Greeter())
253162
.buildAndListen()
254163
}
255164
```
@@ -265,7 +174,7 @@ gradle run
265174
To deploy the Restate service as Lambda, add [`sdk-lambda`](sdk-lambda) to the dependencies. For example, in Gradle:
266175

267176
```
268-
implementation("dev.restate:sdk-lambda:0.6.0")
177+
implementation("dev.restate:sdk-lambda:0.9.0")
269178
```
270179

271180
Configure the build tool to generate Fat-JARs, which are required by AWS Lambda to correctly load the JAR. For example, using Gradle:
@@ -285,7 +194,7 @@ Now create the Lambda handler invoking the service. For example, in Java:
285194
public class MyLambdaHandler extends BaseRestateLambdaHandler {
286195
@Override
287196
public void register(RestateLambdaEndpointBuilder builder) {
288-
builder.withService(new Greeter());
197+
builder.bind(new Greeter());
289198
}
290199
}
291200
```
@@ -295,7 +204,7 @@ In Kotlin:
295204
```kotlin
296205
class MyLambdaHandler : BaseRestateLambdaHandler {
297206
override fun register(builder: RestateLambdaEndpointBuilder) {
298-
builder.withService(Greeter())
207+
builder.bind(Greeter())
299208
}
300209
}
301210
```
@@ -310,22 +219,6 @@ You can now upload the generated Jar in AWS Lambda, and configure `MyLambdaHandl
310219

311220
### Additional setup
312221

313-
#### State ser/de using Jackson
314-
315-
State ser/de is defined by the interface `Serde`. If you want to use [Jackson Databind](https://github.com/FasterXML/jackson) to ser/de POJOs to JSON, add the dependency [`sdk-serde-jackson`](sdk-serde-jackson).
316-
317-
For example, in Gradle:
318-
319-
```
320-
implementation("dev.restate:sdk-serde-jackson:0.6.0")
321-
```
322-
323-
And then use `JacksonSerdes`:
324-
325-
```java
326-
private static final StateKey<Person> PERSON = StateKey.of("person", JacksonSerdes.of(Person.class));
327-
```
328-
329222
#### Logging
330223

331224
The SDK uses log4j2 as logging facade. To enable logging, add the `log4j2` implementation to the dependencies:
@@ -433,12 +326,6 @@ To publish local snapshots of the project:
433326
./gradlew -DskipSigning publishToMavenLocal
434327
```
435328

436-
To update the [`proto`](https://github.com/restatedev/proto/) git subtree:
437-
438-
```shell
439-
git subtree pull --prefix sdk-common/src/main/proto/ git@github.com:restatedev/proto.git main --squash
440-
```
441-
442329
To update the [`service-protocol`](https://github.com/restatedev/service-protocol/) git subtree:
443330

444331
```shell

0 commit comments

Comments
 (0)