{"id":29228238,"url":"https://github.com/restatedev/sdk-java","last_synced_at":"2026-02-03T14:09:27.213Z","repository":{"id":208687776,"uuid":"569181470","full_name":"restatedev/sdk-java","owner":"restatedev","description":"Restate SDK for JVM Languages","archived":false,"fork":false,"pushed_at":"2025-07-02T21:44:58.000Z","size":2142,"stargazers_count":35,"open_issues_count":11,"forks_count":7,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-03T10:06:52.062Z","etag":null,"topics":["distributed-systems","java","jvm","kotlin","kotlin-coroutines"],"latest_commit_sha":null,"homepage":"https://restate.dev","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/restatedev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-11-22T09:04:16.000Z","updated_at":"2025-07-02T21:45:01.000Z","dependencies_parsed_at":"2024-10-18T03:33:17.038Z","dependency_job_id":"8e41d651-7b32-4c1e-8686-25654760db48","html_url":"https://github.com/restatedev/sdk-java","commit_stats":null,"previous_names":["restatedev/sdk-java"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/restatedev/sdk-java","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restatedev%2Fsdk-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restatedev%2Fsdk-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restatedev%2Fsdk-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restatedev%2Fsdk-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/restatedev","download_url":"https://codeload.github.com/restatedev/sdk-java/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restatedev%2Fsdk-java/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264777821,"owners_count":23662555,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["distributed-systems","java","jvm","kotlin","kotlin-coroutines"],"created_at":"2025-07-03T10:04:12.111Z","updated_at":"2026-02-03T14:09:27.202Z","avatar_url":"https://github.com/restatedev.png","language":"Java","funding_links":[],"categories":["开发框架"],"sub_categories":["微服务框架"],"readme":"[![Documentation](https://img.shields.io/badge/doc-reference-blue)](https://docs.restate.dev)\n[![Java](https://img.shields.io/badge/Javadoc-blue?logo=readthedocs)](http://restatedev.github.io/sdk-java/javadocs/)\n[![Kotlindocs](https://img.shields.io/badge/Kotlindocs-blue?logo=kotlin)](http://restatedev.github.io/sdk-java/ktdocs/)\n[![Examples](https://img.shields.io/badge/view-examples-blue)](https://github.com/restatedev/examples)\n[![Discord](https://img.shields.io/discord/1128210118216007792?logo=discord)](https://discord.gg/skW3AZ6uGd)\n[![Twitter](https://img.shields.io/twitter/follow/restatedev.svg?style=social\u0026label=Follow)](https://twitter.com/intent/follow?screen_name=restatedev)\n\n# Restate JVM SDK\n\n[Restate](https://restate.dev/) is a system for easily building resilient applications using _distributed durable async/await_. This repository contains the Restate SDK for writing services using JVM languages.\n\nThis SDK features:\n\n- Implement Restate services using either:\n  - Java\n  - Kotlin coroutines\n- Deploy Restate services as:\n  - Non-blocking HTTP servers\n  - On AWS Lambda\n\n## Community\n\n* 🤗️ [Join our online community](https://discord.gg/skW3AZ6uGd) for help, sharing feedback and talking to the community.\n* 📖 [Check out our documentation](https://docs.restate.dev) to get quickly started!\n* 📣 [Follow us on Twitter](https://twitter.com/restatedev) for staying up to date.\n* 🙋 [Create a GitHub issue](https://github.com/restatedev/sdk-java/issues) for requesting a new feature or reporting a problem.\n* 🏠 [Visit our GitHub org](https://github.com/restatedev) for exploring other repositories.\n\n## Using the SDK\n\n### Prerequisites\n- JDK \u003e= 17\n\n### tl;dr Use project templates\n\nTo get started, follow the [Java quickstart](https://docs.restate.dev/get_started/quickstart?sdk=java) or the [Kotlin quickstart](https://docs.restate.dev/get_started/quickstart?sdk=kotlin).\n\n### Setup a project (Java)\n\nScaffold a project using the build tool of your choice. For example, with Gradle (Kotlin script):\n\n```\ngradle init --type java-application\n```\n\nAdd the annotation processor dependency [sdk-api-gen](sdk-api-gen), and then, depending on whether you want to deploy using HTTP or Lambda, use the appropriate dependency:\n\n```kotlin\nannotationProcessor(\"dev.restate:sdk-api-gen:2.4.1\")\n\n// For HTTP services\nimplementation(\"dev.restate:sdk-java-http:2.4.1\")\n// For Lambda services\n// implementation(\"dev.restate:sdk-java-lambda:2.4.1\")\n```\n\n### Setup a project (Kotlin)\n\nScaffold a project using the build tool of your choice. For example, with Gradle (Kotlin script):\n\n```\ngradle init --type kotlin-application\n```\n\nAdd the [Kotlin symbol processing](https://kotlinlang.org/docs/ksp-quickstart.html#use-your-own-processor-in-a-project) plugin:\n\n```\nplugins {\n    id(\"com.google.devtools.ksp\") version \"2.2.10-2.0.2\"\n}\n```\n\nAdd the ksp dependency [sdk-api-gen](sdk-api-kotlin-gen), and then, depending on whether you want to deploy using HTTP or Lambda, use the appropriate dependency:\n\n```kotlin\nksp(\"dev.restate:sdk-api-kotlin-gen:2.4.1\")\n\n// For HTTP services\nimplementation(\"dev.restate:sdk-kotlin-http:2.4.1\")\n// For Lambda services\n// implementation(\"dev.restate:sdk-kotlin-lambda:2.4.1\")\n```\n\n### Implement your first Restate component (Java)\n\nImplement your first virtual object in a new class, for example:\n\n```java\nimport dev.restate.sdk.ObjectContext;\nimport dev.restate.sdk.annotation.Handler;\nimport dev.restate.sdk.annotation.VirtualObject;\nimport dev.restate.sdk.common.StateKey;\n\n@VirtualObject\npublic class Greeter {\n\n  private static final StateKey\u003cLong\u003e COUNT = StateKey.of(\"total\", Long.class);\n\n  @Handler\n  public String greet(ObjectContext ctx, String name) {\n    long count = ctx.get(COUNT).orElse(0L);\n    ctx.set(COUNT, count + 1);\n\n    return String.format(\"Hello %s for the %d time!\", name, count);\n  }\n}\n```\n\nBy default, [Jackson Databind](https://github.com/FasterXML/jackson) will be used for serialization/deserialization. You can override this configuration by customizing the `SerdeFactory`, check out the javadocs for more details.\n\n### Implement your first Restate component (Kotlin)\n\nImplement your first virtual object in a new class, for example:\n\n```kotlin\nimport dev.restate.sdk.annotation.*\nimport dev.restate.sdk.kotlin.*\n\n@VirtualObject\nclass Greeter {\n  companion object {\n    private val COUNT = stateKey(\"total\")\n  }\n\n  @Handler\n  suspend fun greet(context: ObjectContext, name: String): String {\n    val count = context.get(COUNT) ?: 0L\n    context.set(COUNT, count + 1)\n    return \"Hello $name for the $count time!\"\n  }\n}\n```\n\nBy default [`kotlinx.serialization`](https://github.com/Kotlin/kotlinx.serialization?tab=readme-ov-file#setup) will be used for serialization/deserialization. You can override this configuration by customizing the `SerdeFactory`, check out the javadocs for more details.\n\n### Deploy the service (HTTP Server)\n\nTo deploy the Restate service as HTTP server, add the following code to the `main`. For example in Java:\n\n```java\npublic static void main(String[] args) {\n  RestateHttpServer.listen(\n    Endpoint.bind(new Greeter())\n  );\n}\n```\n\nIn Kotlin:\n\n```kotlin\nfun main() {\n  RestateHttpServer.listen(\n    endpoint {\n      bind(Greeter())\n    }\n  )\n}\n```\n\nExecute the project. For example, using Gradle:\n\n```\ngradle run\n```\n\n### Deploy the service (AWS Lambda)\n\nTo deploy the Restate service as Lambda, configure the build tool to generate Fat-JARs, which are required by AWS Lambda to correctly load the JAR.\nFor example, using Gradle:\n\n```\nplugins {\n  // ...\n  // The shadow plugin generates a shadow JAR ready for AWS Lambda\n  id(\"com.github.johnrengelman.shadow\").version(\"7.1.2\")\n  // ...\n}\n```\n\nNow create the Lambda handler invoking the service. For example, in Java:\n\n```java\npublic class MyLambdaHandler extends BaseRestateLambdaHandler {\n  @Override\n  public void register(Endpoint.Builder builder) {\n    builder.bind(new Greeter());\n  }\n}\n```\n\nIn Kotlin:\n\n```kotlin\nclass MyLambdaHandler : BaseRestateLambdaHandler {\n  override fun register(builder: Endpoint.Builder) {\n    builder.bind(Greeter())\n  }\n}\n```\n\nNow build the Fat-JAR. For example, using Gradle:\n\n```\ngradle shadowJar\n```\n\nYou can now upload the generated Jar in AWS Lambda, and configure `MyLambdaHandler` as the Lambda class in the AWS UI.\n\n### Additional setup\n\n#### Logging\n\nThe SDK uses log4j2 as logging facade, to configure it add the file `resources/log4j2.properties`:\n\n```\n# Set to debug or trace if log4j initialization is failing\nstatus = warn\n\n# Console appender configuration\nappender.console.type = Console\nappender.console.name = consoleLogger\nappender.console.layout.type = PatternLayout\nappender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %notEmpty{[%X{restateInvocationTarget}]}%notEmpty{[%X{restateInvocationId}]} %c - %m%n\n\n# Filter out logging during replay\nappender.console.filter.replay.type = ContextMapFilter\nappender.console.filter.replay.onMatch = DENY\nappender.console.filter.replay.onMismatch = NEUTRAL\nappender.console.filter.replay.0.type = KeyValuePair\nappender.console.filter.replay.0.key = restateInvocationStatus\nappender.console.filter.replay.0.value = REPLAYING\n\n# Restate logs to debug level\nlogger.app.name = dev.restate\nlogger.app.level = info\nlogger.app.additivity = false\nlogger.app.appenderRef.console.ref = consoleLogger\n\n# Root logger\nrootLogger.level = info\nrootLogger.appenderRef.stdout.ref = consoleLogger\n```\n\nThe SDK injects the following additional metadata to the logging context that can be used for filtering as well:\n\n* `restateInvocationTarget`: invocation target, e.g. `counter.Counter/Add`.\n* `restateInvocationId`: Invocation identifier, to be used in Restate observability tools. See https://docs.restate.dev/operate/invocation#invocation-identifier.\n* `restateInvocationStatus`: Invocation status, can be `WAITING_START`, `REPLAYING`, `PROCESSING`, `CLOSED`.\n\nThe dependencies `sdk-java-http`, `sdk-java-lambda`, `sdk-kotlin-http` and `sdk-kotlin-lambda` bring in `log4j-core` by default, but you can easily exclude/override that if you need to.\n\nWhen assembling fat-jars, make sure to enable merging META-INF/services files. For more info, see https://github.com/apache/logging-log4j2/issues/2099.\n\n#### Tracing with OpenTelemetry\n\nThe SDK automatically propagates the OpenTelemetry `Context` from the `restate-server` into your handler. You can use that to create custom spans.\n\nTo configure the `OpenTelemetry` that should be used by the SDK to publish traces, configure it in the `Endpoint.Builder` object.\n\nFor example, to set up tracing using environment variables, add the following modules to your dependencies:\n\n```\nimplementation(\"io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.38.0\")\nimplementation(\"io.opentelemetry:opentelemetry-exporter-otlp:1.38.0\")\n```\n\nAnd then configure it in the endpoint builder:\n\n```java\n.withOpenTelemetry(AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk())\n```\n\nBy exporting the following environment variables the OpenTelemetry SDK will be automatically configured to push traces:\n\n```shell\nexport OTEL_SERVICE_NAME=my-service\nexport OTEL_TRACES_SAMPLER=always_on\nexport OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:14250\n```\n\nPlease refer to the [Opentelemetry manual instrumentation documentation](https://opentelemetry.io/docs/instrumentation/java/manual/#manual-instrumentation-setup) and the [autoconfigure documentation](https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/autoconfigure/README.md) for more info. \n\nSee https://docs.restate.dev/operate/monitoring/tracing to configure Restate tracing.\n\n## Versions\n\nThis library follows [Semantic Versioning](https://semver.org/).\n\nThe compatibility with Restate is described in the following table:\n\n| Restate Server\\sdk-java | \u003c 2.0            | 2.0 - 2.1 | 2.2 - 2.3        | 2.4              |\n|-------------------------|------------------|-----------|------------------|------------------|\n| \u003c 1.3                   | ✅                | ❌         | ❌                | ❌                |\n| 1.3                     | ✅                | ✅         | ✅ \u003csup\u003e(1)\u003c/sup\u003e | ✅ \u003csup\u003e(2)\u003c/sup\u003e |\n| 1.4                     | ✅                | ✅         | ✅                | ✅ \u003csup\u003e(2)\u003c/sup\u003e |\n| 1.5                     | ⚠ \u003csup\u003e(3)\u003c/sup\u003e | ✅         | ✅                | ✅                |\n\n\u003csup\u003e(1)\u003c/sup\u003e **Note** The new service/handler configuration options `inactivityTimeout`, `abortTimeout`, `idempotencyRetention`, `journalRetention`, `ingressPrivate`, `enableLazyState` work only from Restate 1.4 onward.\n\n\u003csup\u003e(2)\u003c/sup\u003e **Note** The new service/handler configuration option `invocationRetryPolicy` works only from Restate 1.5 onward.\n\n\u003csup\u003e(3)\u003c/sup\u003e **Warning** SDK versions \u003c 2.0 are deprecated, and cannot be registered anymore. Check the [Restate 1.5 release notes](https://github.com/restatedev/restate/releases/tag/v1.5.0) for more info.\n\n## Contributing\n\nWe’re excited if you join the Restate community and start contributing!\nWhether it is feature requests, bug reports, ideas \u0026 feedback or PRs, we appreciate any and all contributions.\nWe know that your time is precious and, therefore, deeply value any effort to contribute!\n\n### Building the SDK locally\n\nPrerequisites:\n\n- JDK \u003e= 17\n- Docker or Podman\n\nTo build the SDK:\n\n```shell\n./gradlew build\n```\n\nTo run the tests:\n\n```shell\n./gradlew check\n```\n\nTo publish local snapshots of the project:\n\n```shell\n./gradlew -DskipSigning publishToMavenLocal\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frestatedev%2Fsdk-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frestatedev%2Fsdk-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frestatedev%2Fsdk-java/lists"}