From 2e7aa90251d95c387b5795379a023553266b49e8 Mon Sep 17 00:00:00 2001 From: slinkydeveloper Date: Fri, 24 Nov 2023 10:37:38 +0100 Subject: [PATCH] Fix all the package names to use the new release artifacts Update READMEs Add tests --- jvm/java-blocking-http/README.md | 22 +++++++-- jvm/java-blocking-http/build.gradle.kts | 44 +++++++++--------- .../dev/restate/sdk/examples/GreeterTest.java | 34 ++++++++++++++ jvm/java-blocking-lambda/README.md | 25 +++++++--- jvm/java-blocking-lambda/build.gradle.kts | 39 ++++++++-------- .../dev/restate/sdk/examples/Greeter.java | 1 - .../restate/sdk/examples/LambdaFactory.java | 11 ----- .../restate/sdk/examples/LambdaHandler.java | 11 +++++ ...tate.sdk.lambda.LambdaRestateServerFactory | 1 - .../dev/restate/sdk/examples/GreeterTest.java | 34 ++++++++++++++ jvm/kotlin-http/README.md | 22 +++++++-- jvm/kotlin-http/build.gradle.kts | 46 +++++++++++-------- .../dev/restate/sdk/examples/Greeter.kt | 6 ++- .../dev/restate/sdk/examples/GreeterTest.kt | 33 +++++++++++++ jvm/kotlin-lambda/README.md | 23 ++++++++-- jvm/kotlin-lambda/build.gradle.kts | 38 +++++++-------- .../dev/restate/sdk/examples/Greeter.kt | 4 +- .../dev/restate/sdk/examples/LambdaFactory.kt | 10 ---- .../dev/restate/sdk/examples/LambdaHandler.kt | 10 ++++ .../dev/restate/sdk/examples/GreeterTest.kt | 33 +++++++++++++ 20 files changed, 322 insertions(+), 125 deletions(-) create mode 100644 jvm/java-blocking-http/src/test/java/dev/restate/sdk/examples/GreeterTest.java delete mode 100644 jvm/java-blocking-lambda/src/main/java/dev/restate/sdk/examples/LambdaFactory.java create mode 100644 jvm/java-blocking-lambda/src/main/java/dev/restate/sdk/examples/LambdaHandler.java delete mode 100644 jvm/java-blocking-lambda/src/main/resources/META-INF/services/dev.restate.sdk.lambda.LambdaRestateServerFactory create mode 100644 jvm/java-blocking-lambda/src/test/java/dev/restate/sdk/examples/GreeterTest.java create mode 100644 jvm/kotlin-http/src/test/kotlin/dev/restate/sdk/examples/GreeterTest.kt delete mode 100644 jvm/kotlin-lambda/src/main/kotlin/dev/restate/sdk/examples/LambdaFactory.kt create mode 100644 jvm/kotlin-lambda/src/main/kotlin/dev/restate/sdk/examples/LambdaHandler.kt create mode 100644 jvm/kotlin-lambda/src/test/kotlin/dev/restate/sdk/examples/GreeterTest.kt diff --git a/jvm/java-blocking-http/README.md b/jvm/java-blocking-http/README.md index 3203360d..2b1330b7 100644 --- a/jvm/java-blocking-http/README.md +++ b/jvm/java-blocking-http/README.md @@ -1,10 +1,12 @@ # Blocking HTTP example -Example with Java blocking interface and HTTP server. +Sample project configuration of a Restate service using the Java blocking interface and HTTP server. It contains: -## Setup credentials - -Because the SDK is not public yet, you need to set up the PAT credentials, see https://github.com/restatedev/e2e#setup-local-env +* [`build.gradle.kts`](build.gradle.kts) +* [Service interface definition `greeter.proto`](src/main/proto/greeter.proto) +* [Service class implementation `Greeter`](src/main/java/dev/restate/sdk/examples/Greeter.java) +* [Test `GreeterTest`](src/test/java/dev/restate/sdk/examples/GreeterTest.java) +* [Logging configuration](src/main/resources/log4j2.properties) ## Running the example @@ -14,4 +16,14 @@ You can run the Java greeter service via: ./gradlew run ``` -Or from the Intellij IDEA UI. +Or from the IDE UI. + +## Running the tests + +You can run the tests either via: + +```shell +./gradlew check +``` + +Or from the IDE UI. \ No newline at end of file diff --git a/jvm/java-blocking-http/build.gradle.kts b/jvm/java-blocking-http/build.gradle.kts index 4fcded0e..6e1a50a9 100644 --- a/jvm/java-blocking-http/build.gradle.kts +++ b/jvm/java-blocking-http/build.gradle.kts @@ -7,23 +7,21 @@ plugins { id("com.google.protobuf") version "0.9.1" } -dependencies { - repositories { - mavenCentral() - maven { - url = uri("https://maven.pkg.github.com/restatedev/sdk-java") - credentials { - username = System.getenv("GH_PACKAGE_READ_ACCESS_USER") - password = System.getenv("GH_PACKAGE_READ_ACCESS_TOKEN") - } - } - } +repositories { + mavenCentral() + // OSSRH Snapshots repo + // TODO remove it once we have the proper release + maven { url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") } +} + +val restateVersion = "0.0.1-SNAPSHOT" +dependencies { // Restate SDK - implementation("dev.restate.sdk:sdk-java-blocking:1.0-SNAPSHOT") - implementation("dev.restate.sdk:sdk-http-vertx:1.0-SNAPSHOT") + implementation("dev.restate:sdk-java-blocking:$restateVersion") + implementation("dev.restate:sdk-http-vertx:$restateVersion") // To use Jackson to read/write state entries (optional) - implementation("dev.restate.sdk:sdk-serde-jackson:1.0-SNAPSHOT") + implementation("dev.restate:sdk-serde-jackson:$restateVersion") // Protobuf and grpc dependencies implementation("com.google.protobuf:protobuf-java:3.24.3") @@ -35,6 +33,10 @@ dependencies { // Logging (optional) implementation("org.apache.logging.log4j:log4j-core:2.20.0") + + // Testing (optional) + testImplementation("org.junit.jupiter:junit-jupiter:5.9.1") + testImplementation("dev.restate:sdk-test:$restateVersion") } // Configure protoc plugin @@ -44,7 +46,7 @@ protobuf { // We need both grpc and restate codegen(s) because the restate codegen depends on the grpc one plugins { id("grpc") { artifact = "io.grpc:protoc-gen-grpc-java:1.58.0" } - id("restate") { artifact = "dev.restate.sdk:protoc-gen-restate-java-blocking:1.0-SNAPSHOT:all@jar" } + id("restate") { artifact = "dev.restate:protoc-gen-restate-java-blocking:$restateVersion:all@jar" } } generateProtoTasks { @@ -57,12 +59,12 @@ protobuf { } } -application { - mainClass.set("dev.restate.sdk.examples.Greeter") +// Configure test platform +tasks.withType { + useJUnitPlatform() } -// Temporary solution for disabling caching of Java SDK until we release it -configurations.all { - // This disables caching for -SNAPSHOT dependencies - resolutionStrategy.cacheChangingModulesFor(0, "seconds") +// Set main class +application { + mainClass.set("dev.restate.sdk.examples.Greeter") } \ No newline at end of file diff --git a/jvm/java-blocking-http/src/test/java/dev/restate/sdk/examples/GreeterTest.java b/jvm/java-blocking-http/src/test/java/dev/restate/sdk/examples/GreeterTest.java new file mode 100644 index 00000000..9f6f94c3 --- /dev/null +++ b/jvm/java-blocking-http/src/test/java/dev/restate/sdk/examples/GreeterTest.java @@ -0,0 +1,34 @@ +package dev.restate.sdk.examples; + +import dev.restate.sdk.examples.generated.GreeterGrpc; +import dev.restate.sdk.examples.generated.GreeterGrpc.GreeterBlockingStub; +import dev.restate.sdk.examples.generated.GreeterProto.GreetRequest; +import dev.restate.sdk.examples.generated.GreeterProto.GreetResponse; +import dev.restate.sdk.testing.RestateGrpcChannel; +import dev.restate.sdk.testing.RestateRunner; +import dev.restate.sdk.testing.RestateRunnerBuilder; +import io.grpc.ManagedChannel; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class GreeterTest { + + // Runner runs Restate using testcontainers and registers services + @RegisterExtension + private static final RestateRunner restateRunner = RestateRunnerBuilder.create() + // Service to test + .withService(new Greeter()) + .buildRunner(); + + @Test + void testGreet( + // Channel to send requests to Restate services + @RestateGrpcChannel ManagedChannel channel) { + GreeterBlockingStub client = GreeterGrpc.newBlockingStub(channel); + GreetResponse response = client.greet(GreetRequest.newBuilder().setName("Francesco").build()); + + assertEquals("Hello Francesco for the 1 time!", response.getMessage()); + } +} diff --git a/jvm/java-blocking-lambda/README.md b/jvm/java-blocking-lambda/README.md index fa591a22..51a28d33 100644 --- a/jvm/java-blocking-lambda/README.md +++ b/jvm/java-blocking-lambda/README.md @@ -1,10 +1,13 @@ -# Blocking HTTP example +# Blocking Lambda example -Example with Java blocking interface and Lambda. +Sample project configuration of a Restate service using the Java blocking interface and AWS Lambda. It contains: -## Setup credentials - -Because the SDK is not public yet, you need to set up the PAT credentials, see https://github.com/restatedev/e2e#setup-local-env +* [`build.gradle.kts`](build.gradle.kts) +* [Service interface definition `greeter.proto`](src/main/proto/greeter.proto) +* [Service class implementation `Greeter`](src/main/java/dev/restate/sdk/examples/Greeter.java) +* [Lambda handler `LambdaHandler`](src/main/java/dev/restate/sdk/examples/LambdaHandler.java) +* [Test `GreeterTest`](src/test/java/dev/restate/sdk/examples/GreeterTest.java) +* [Logging configuration](src/main/resources/log4j2.properties) ## Package @@ -16,4 +19,14 @@ Run: You'll find the shadowed jar in the `build` directory. -The class to configure in Lambda is `dev.restate.sdk.lambda.LambdaHandler`. +The class to configure in Lambda is `dev.restate.sdk.examples.LambdaHandler`. + +## Running the tests + +You can run the tests either via: + +```shell +./gradlew check +``` + +Or from the IDE UI. \ No newline at end of file diff --git a/jvm/java-blocking-lambda/build.gradle.kts b/jvm/java-blocking-lambda/build.gradle.kts index 60881dd1..6235cce1 100644 --- a/jvm/java-blocking-lambda/build.gradle.kts +++ b/jvm/java-blocking-lambda/build.gradle.kts @@ -9,23 +9,21 @@ plugins { id("com.github.johnrengelman.shadow") version "7.1.2" } -dependencies { - repositories { - mavenCentral() - maven { - url = uri("https://maven.pkg.github.com/restatedev/sdk-java") - credentials { - username = System.getenv("GH_PACKAGE_READ_ACCESS_USER") - password = System.getenv("GH_PACKAGE_READ_ACCESS_TOKEN") - } - } - } +repositories { + mavenCentral() + // OSSRH Snapshots repo + // TODO remove it once we have the proper release + maven { url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") } +} + +val restateVersion = "0.0.1-SNAPSHOT" +dependencies { // Restate SDK - implementation("dev.restate.sdk:sdk-java-blocking:1.0-SNAPSHOT") - implementation("dev.restate.sdk:sdk-lambda:1.0-SNAPSHOT") + implementation("dev.restate:sdk-java-blocking:$restateVersion") + implementation("dev.restate:sdk-lambda:$restateVersion") // To use Jackson to read/write state entries (optional) - implementation("dev.restate.sdk:sdk-serde-jackson:1.0-SNAPSHOT") + implementation("dev.restate:sdk-serde-jackson:$restateVersion") // Protobuf and grpc dependencies implementation("com.google.protobuf:protobuf-java:3.24.3") @@ -37,6 +35,10 @@ dependencies { // Logging (optional) implementation("org.apache.logging.log4j:log4j-core:2.20.0") + + // Testing (optional) + testImplementation("org.junit.jupiter:junit-jupiter:5.9.1") + testImplementation("dev.restate:sdk-test:$restateVersion") } // Configure protoc plugin @@ -46,7 +48,7 @@ protobuf { // We need both grpc and restate codegen(s) because the restate codegen depends on the grpc one plugins { id("grpc") { artifact = "io.grpc:protoc-gen-grpc-java:1.58.0" } - id("restate") { artifact = "dev.restate.sdk:protoc-gen-restate-java-blocking:1.0-SNAPSHOT:all@jar" } + id("restate") { artifact = "dev.restate:protoc-gen-restate-java-blocking:$restateVersion:all@jar" } } generateProtoTasks { @@ -59,8 +61,7 @@ protobuf { } } -// Temporary solution for disabling caching of Java SDK until we release it -configurations.all { - // This disables caching for -SNAPSHOT dependencies - resolutionStrategy.cacheChangingModulesFor(0, "seconds") +// Configure test platform +tasks.withType { + useJUnitPlatform() } diff --git a/jvm/java-blocking-lambda/src/main/java/dev/restate/sdk/examples/Greeter.java b/jvm/java-blocking-lambda/src/main/java/dev/restate/sdk/examples/Greeter.java index 4392d373..c8120364 100644 --- a/jvm/java-blocking-lambda/src/main/java/dev/restate/sdk/examples/Greeter.java +++ b/jvm/java-blocking-lambda/src/main/java/dev/restate/sdk/examples/Greeter.java @@ -4,7 +4,6 @@ import dev.restate.sdk.core.CoreSerdes; import dev.restate.sdk.core.StateKey; import dev.restate.sdk.examples.generated.*; -import dev.restate.sdk.http.vertx.RestateHttpEndpointBuilder; import static dev.restate.sdk.examples.generated.GreeterProto.*; diff --git a/jvm/java-blocking-lambda/src/main/java/dev/restate/sdk/examples/LambdaFactory.java b/jvm/java-blocking-lambda/src/main/java/dev/restate/sdk/examples/LambdaFactory.java deleted file mode 100644 index a024d3e3..00000000 --- a/jvm/java-blocking-lambda/src/main/java/dev/restate/sdk/examples/LambdaFactory.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.restate.sdk.examples; - -import dev.restate.sdk.lambda.LambdaRestateServer; -import dev.restate.sdk.lambda.LambdaRestateServerFactory; - -public class LambdaFactory implements LambdaRestateServerFactory { - @Override - public LambdaRestateServer create() { - return LambdaRestateServer.builder().withService(new Greeter()).build(); - } -} diff --git a/jvm/java-blocking-lambda/src/main/java/dev/restate/sdk/examples/LambdaHandler.java b/jvm/java-blocking-lambda/src/main/java/dev/restate/sdk/examples/LambdaHandler.java new file mode 100644 index 00000000..ada419e9 --- /dev/null +++ b/jvm/java-blocking-lambda/src/main/java/dev/restate/sdk/examples/LambdaHandler.java @@ -0,0 +1,11 @@ +package dev.restate.sdk.examples; + +import dev.restate.sdk.lambda.BaseRestateLambdaHandler; +import dev.restate.sdk.lambda.RestateLambdaEndpointBuilder; + +public class LambdaHandler extends BaseRestateLambdaHandler { + @Override + public void register(RestateLambdaEndpointBuilder builder) { +builder.withService(new Greeter()); + } +} diff --git a/jvm/java-blocking-lambda/src/main/resources/META-INF/services/dev.restate.sdk.lambda.LambdaRestateServerFactory b/jvm/java-blocking-lambda/src/main/resources/META-INF/services/dev.restate.sdk.lambda.LambdaRestateServerFactory deleted file mode 100644 index 297dab9e..00000000 --- a/jvm/java-blocking-lambda/src/main/resources/META-INF/services/dev.restate.sdk.lambda.LambdaRestateServerFactory +++ /dev/null @@ -1 +0,0 @@ -dev.restate.sdk.examples.LambdaFactory \ No newline at end of file diff --git a/jvm/java-blocking-lambda/src/test/java/dev/restate/sdk/examples/GreeterTest.java b/jvm/java-blocking-lambda/src/test/java/dev/restate/sdk/examples/GreeterTest.java new file mode 100644 index 00000000..9f6f94c3 --- /dev/null +++ b/jvm/java-blocking-lambda/src/test/java/dev/restate/sdk/examples/GreeterTest.java @@ -0,0 +1,34 @@ +package dev.restate.sdk.examples; + +import dev.restate.sdk.examples.generated.GreeterGrpc; +import dev.restate.sdk.examples.generated.GreeterGrpc.GreeterBlockingStub; +import dev.restate.sdk.examples.generated.GreeterProto.GreetRequest; +import dev.restate.sdk.examples.generated.GreeterProto.GreetResponse; +import dev.restate.sdk.testing.RestateGrpcChannel; +import dev.restate.sdk.testing.RestateRunner; +import dev.restate.sdk.testing.RestateRunnerBuilder; +import io.grpc.ManagedChannel; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class GreeterTest { + + // Runner runs Restate using testcontainers and registers services + @RegisterExtension + private static final RestateRunner restateRunner = RestateRunnerBuilder.create() + // Service to test + .withService(new Greeter()) + .buildRunner(); + + @Test + void testGreet( + // Channel to send requests to Restate services + @RestateGrpcChannel ManagedChannel channel) { + GreeterBlockingStub client = GreeterGrpc.newBlockingStub(channel); + GreetResponse response = client.greet(GreetRequest.newBuilder().setName("Francesco").build()); + + assertEquals("Hello Francesco for the 1 time!", response.getMessage()); + } +} diff --git a/jvm/kotlin-http/README.md b/jvm/kotlin-http/README.md index 72b600bc..ca6ea9ae 100644 --- a/jvm/kotlin-http/README.md +++ b/jvm/kotlin-http/README.md @@ -1,10 +1,12 @@ # Kotlin HTTP example -Example with Kotlin coroutines interface and HTTP server. +Sample project configuration of a Restate service using the Kotlin coroutines interface and HTTP server. It contains: -## Setup credentials - -Because the SDK is not public yet, you need to set up the PAT credentials, see https://github.com/restatedev/e2e#setup-local-env +* [`build.gradle.kts`](build.gradle.kts) +* [Service interface definition `greeter.proto`](src/main/proto/greeter.proto) +* [Service class implementation `Greeter`](src/main/kotlin/dev/restate/sdk/examples/Greeter.kt) +* [Test `GreeterTest`](src/test/kotlin/dev/restate/sdk/examples/GreeterTest.kt) +* [Logging configuration](src/main/resources/log4j2.properties) ## Running the example @@ -14,4 +16,14 @@ You can run the Kotlin greeter service via: ./gradlew run ``` -Or from the Intellij IDEA UI. +Or from the IDE UI. + +## Running the tests + +You can run the tests either via: + +```shell +./gradlew check +``` + +Or from the IDE UI. diff --git a/jvm/kotlin-http/build.gradle.kts b/jvm/kotlin-http/build.gradle.kts index 1c34063b..aeb8c5cb 100644 --- a/jvm/kotlin-http/build.gradle.kts +++ b/jvm/kotlin-http/build.gradle.kts @@ -8,23 +8,21 @@ plugins { id("com.google.protobuf") version "0.9.1" } -dependencies { - repositories { - mavenCentral() - maven { - url = uri("https://maven.pkg.github.com/restatedev/sdk-java") - credentials { - username = System.getenv("GH_PACKAGE_READ_ACCESS_USER") - password = System.getenv("GH_PACKAGE_READ_ACCESS_TOKEN") - } - } - } +repositories { + mavenCentral() + // OSSRH Snapshots repo + // TODO remove it once we have the proper release + maven { url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") } +} + +val restateVersion = "0.0.1-SNAPSHOT" +dependencies { // Restate SDK - implementation("dev.restate.sdk:sdk-kotlin:1.0-SNAPSHOT") - implementation("dev.restate.sdk:sdk-http-vertx:1.0-SNAPSHOT") + implementation("dev.restate:sdk-kotlin:$restateVersion") + implementation("dev.restate:sdk-http-vertx:$restateVersion") // To use Jackson to read/write state entries (optional) - implementation("dev.restate.sdk:sdk-serde-jackson:1.0-SNAPSHOT") + implementation("dev.restate:sdk-serde-jackson:$restateVersion") // Protobuf and grpc dependencies (we need the Java dependencies as well because the Kotlin dependencies rely on Java) implementation("com.google.protobuf:protobuf-java:3.24.3") @@ -36,8 +34,16 @@ dependencies { // See https://github.com/grpc/grpc-java/issues/9153 compileOnly("org.apache.tomcat:annotations-api:6.0.53") + // To specify the coroutines dispatcher + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") + // Logging (optional) implementation("org.apache.logging.log4j:log4j-core:2.20.0") + + // Testing (optional) + testImplementation("org.junit.jupiter:junit-jupiter:5.9.1") + testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") + testImplementation("dev.restate:sdk-test:$restateVersion") } // Setup Java/Kotlin compiler target @@ -71,12 +77,12 @@ protobuf { } } +// Configure test platform +tasks.withType { + useJUnitPlatform() +} + +// Configure main class application { mainClass.set("dev.restate.sdk.examples.GreeterKt") } - -// Temporary solution for disabling caching of Java SDK until we release it -configurations.all { - // This disables caching for -SNAPSHOT dependencies - resolutionStrategy.cacheChangingModulesFor(0, "seconds") -} \ No newline at end of file diff --git a/jvm/kotlin-http/src/main/kotlin/dev/restate/sdk/examples/Greeter.kt b/jvm/kotlin-http/src/main/kotlin/dev/restate/sdk/examples/Greeter.kt index edb32b87..6baed897 100644 --- a/jvm/kotlin-http/src/main/kotlin/dev/restate/sdk/examples/Greeter.kt +++ b/jvm/kotlin-http/src/main/kotlin/dev/restate/sdk/examples/Greeter.kt @@ -14,7 +14,9 @@ class Greeter : GreeterGrpcKt.GreeterCoroutineImplBase(Dispatchers.Unconfined), RestateCoroutineService { - private val COUNT = StateKey.of("count", CoreSerdes.INT) + companion object { + private val COUNT = StateKey.of("count", CoreSerdes.INT) + } override suspend fun greet(request: GreetRequest): GreetResponse { val ctx = restateContext() @@ -30,6 +32,6 @@ class Greeter : fun main() { RestateHttpEndpointBuilder - .builder(vertx) + .builder() .withService(Greeter()).buildAndListen() } diff --git a/jvm/kotlin-http/src/test/kotlin/dev/restate/sdk/examples/GreeterTest.kt b/jvm/kotlin-http/src/test/kotlin/dev/restate/sdk/examples/GreeterTest.kt new file mode 100644 index 00000000..863fc76b --- /dev/null +++ b/jvm/kotlin-http/src/test/kotlin/dev/restate/sdk/examples/GreeterTest.kt @@ -0,0 +1,33 @@ +package dev.restate.sdk.examples + +import dev.restate.sdk.examples.generated.GreeterGrpcKt.GreeterCoroutineStub +import dev.restate.sdk.examples.generated.greetRequest +import dev.restate.sdk.testing.RestateGrpcChannel +import dev.restate.sdk.testing.RestateRunner +import dev.restate.sdk.testing.RestateRunnerBuilder +import io.grpc.ManagedChannel +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.RegisterExtension + +class GreeterTest { + companion object { + // Runner runs Restate using testcontainers and registers services + @RegisterExtension + private val restateRunner: RestateRunner = RestateRunnerBuilder.create() + // Service to test + .withService(Greeter()) + .buildRunner() + } + + @Test + fun testGreet( + // Channel to send requests to Restate services + @RestateGrpcChannel channel: ManagedChannel) = runTest { + val client = GreeterCoroutineStub(channel) + val response = client.greet(greetRequest { name = "Francesco" }) + + assertEquals("Hello Francesco for the 1 time!", response.getMessage()) + } +} diff --git a/jvm/kotlin-lambda/README.md b/jvm/kotlin-lambda/README.md index 85105a5d..e815b897 100644 --- a/jvm/kotlin-lambda/README.md +++ b/jvm/kotlin-lambda/README.md @@ -1,10 +1,13 @@ # Kotlin Lambda example -Example with Kotlin coroutines interface and Lambda. +Sample project configuration of a Restate service using the Kotlin coroutines interface and AWS Lambda. It contains: -## Setup credentials - -Because the SDK is not public yet, you need to set up the PAT credentials, see https://github.com/restatedev/e2e#setup-local-env +* [`build.gradle.kts`](build.gradle.kts) +* [Service interface definition `greeter.proto`](src/main/proto/greeter.proto) +* [Service class implementation `Greeter`](src/main/kotlin/dev/restate/sdk/examples/Greeter.kt) +* [Lambda handler `LambdaHandler`](src/main/kotlin/dev/restate/sdk/examples/LambdaHandler.kt) +* [Test `GreeterTest`](src/test/kotlin/dev/restate/sdk/examples/GreeterTest.kt) +* [Logging configuration](src/main/resources/log4j2.properties) ## Package @@ -16,4 +19,14 @@ Run: You'll find the shadowed jar in the `build` directory. -The class to configure in Lambda is `dev.restate.sdk.lambda.LambdaHandler`. \ No newline at end of file +The class to configure in Lambda is `dev.restate.sdk.examples.LambdaHandler`. + +## Running the tests + +You can run the tests either via: + +```shell +./gradlew check +``` + +Or from the IDE UI. \ No newline at end of file diff --git a/jvm/kotlin-lambda/build.gradle.kts b/jvm/kotlin-lambda/build.gradle.kts index 1dab49fe..2acf1057 100644 --- a/jvm/kotlin-lambda/build.gradle.kts +++ b/jvm/kotlin-lambda/build.gradle.kts @@ -10,23 +10,21 @@ plugins { id("com.github.johnrengelman.shadow") version "7.1.2" } -dependencies { - repositories { - mavenCentral() - maven { - url = uri("https://maven.pkg.github.com/restatedev/sdk-java") - credentials { - username = System.getenv("GH_PACKAGE_READ_ACCESS_USER") - password = System.getenv("GH_PACKAGE_READ_ACCESS_TOKEN") - } - } - } +repositories { + mavenCentral() + // OSSRH Snapshots repo + // TODO remove it once we have the proper release + maven { url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") } +} + +val restateVersion = "0.0.1-SNAPSHOT" +dependencies { // Restate SDK - implementation("dev.restate.sdk:sdk-kotlin:1.0-SNAPSHOT") - implementation("dev.restate.sdk:sdk-lambda:1.0-SNAPSHOT") + implementation("dev.restate:sdk-kotlin:$restateVersion") + implementation("dev.restate:sdk-lambda:$restateVersion") // To use Jackson to read/write state entries (optional) - implementation("dev.restate.sdk:sdk-serde-jackson:1.0-SNAPSHOT") + implementation("dev.restate:sdk-serde-jackson:$restateVersion") // Protobuf and grpc dependencies (we need the Java dependencies as well because the Kotlin dependencies rely on Java) implementation("com.google.protobuf:protobuf-java:3.24.3") @@ -43,6 +41,11 @@ dependencies { // Logging (optional) implementation("org.apache.logging.log4j:log4j-core:2.20.0") + + // Testing (optional) + testImplementation("org.junit.jupiter:junit-jupiter:5.9.1") + testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") + testImplementation("dev.restate:sdk-test:$restateVersion") } // Setup Java/Kotlin compiler target @@ -76,8 +79,7 @@ protobuf { } } -// Temporary solution for disabling caching of Java SDK until we release it -configurations.all { - // This disables caching for -SNAPSHOT dependencies - resolutionStrategy.cacheChangingModulesFor(0, "seconds") +// Configure test platform +tasks.withType { + useJUnitPlatform() } \ No newline at end of file diff --git a/jvm/kotlin-lambda/src/main/kotlin/dev/restate/sdk/examples/Greeter.kt b/jvm/kotlin-lambda/src/main/kotlin/dev/restate/sdk/examples/Greeter.kt index 18e54005..638c6a3b 100644 --- a/jvm/kotlin-lambda/src/main/kotlin/dev/restate/sdk/examples/Greeter.kt +++ b/jvm/kotlin-lambda/src/main/kotlin/dev/restate/sdk/examples/Greeter.kt @@ -13,7 +13,9 @@ class Greeter : GreeterGrpcKt.GreeterCoroutineImplBase(Dispatchers.Unconfined), RestateCoroutineService { - private val COUNT = StateKey.of("count", CoreSerdes.INT) + companion object { + private val COUNT = StateKey.of("count", CoreSerdes.INT) + } override suspend fun greet(request: GreetRequest): GreetResponse { val ctx = restateContext() diff --git a/jvm/kotlin-lambda/src/main/kotlin/dev/restate/sdk/examples/LambdaFactory.kt b/jvm/kotlin-lambda/src/main/kotlin/dev/restate/sdk/examples/LambdaFactory.kt deleted file mode 100644 index 1222f9c5..00000000 --- a/jvm/kotlin-lambda/src/main/kotlin/dev/restate/sdk/examples/LambdaFactory.kt +++ /dev/null @@ -1,10 +0,0 @@ -package dev.restate.sdk.examples - -import dev.restate.sdk.lambda.LambdaRestateServer -import dev.restate.sdk.lambda.LambdaRestateServerFactory - -class LambdaFactory : LambdaRestateServerFactory { - override fun create(): LambdaRestateServer { - return LambdaRestateServer.builder().withService(Greeter()).build() - } -} diff --git a/jvm/kotlin-lambda/src/main/kotlin/dev/restate/sdk/examples/LambdaHandler.kt b/jvm/kotlin-lambda/src/main/kotlin/dev/restate/sdk/examples/LambdaHandler.kt new file mode 100644 index 00000000..b95f2708 --- /dev/null +++ b/jvm/kotlin-lambda/src/main/kotlin/dev/restate/sdk/examples/LambdaHandler.kt @@ -0,0 +1,10 @@ +package dev.restate.sdk.examples + +import dev.restate.sdk.lambda.BaseRestateLambdaHandler +import dev.restate.sdk.lambda.RestateLambdaEndpointBuilder + +class LambdaHandler : BaseRestateLambdaHandler() { + override fun register(builder: RestateLambdaEndpointBuilder) { + builder.withService(Greeter()) + } +} diff --git a/jvm/kotlin-lambda/src/test/kotlin/dev/restate/sdk/examples/GreeterTest.kt b/jvm/kotlin-lambda/src/test/kotlin/dev/restate/sdk/examples/GreeterTest.kt new file mode 100644 index 00000000..863fc76b --- /dev/null +++ b/jvm/kotlin-lambda/src/test/kotlin/dev/restate/sdk/examples/GreeterTest.kt @@ -0,0 +1,33 @@ +package dev.restate.sdk.examples + +import dev.restate.sdk.examples.generated.GreeterGrpcKt.GreeterCoroutineStub +import dev.restate.sdk.examples.generated.greetRequest +import dev.restate.sdk.testing.RestateGrpcChannel +import dev.restate.sdk.testing.RestateRunner +import dev.restate.sdk.testing.RestateRunnerBuilder +import io.grpc.ManagedChannel +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.RegisterExtension + +class GreeterTest { + companion object { + // Runner runs Restate using testcontainers and registers services + @RegisterExtension + private val restateRunner: RestateRunner = RestateRunnerBuilder.create() + // Service to test + .withService(Greeter()) + .buildRunner() + } + + @Test + fun testGreet( + // Channel to send requests to Restate services + @RestateGrpcChannel channel: ManagedChannel) = runTest { + val client = GreeterCoroutineStub(channel) + val response = client.greet(greetRequest { name = "Francesco" }) + + assertEquals("Hello Francesco for the 1 time!", response.getMessage()) + } +}