⚠️ Pre-release. The Java SDK is at0.1.1— the first version published to Maven Central — and APIs may change before the surface settles. Check the open issues for known gaps. The internal protocol is stable; the Java API surface is still settling.
The Resonate Java SDK lets you build reliable, distributed Java applications on the durable execution programming model. Write ordinary static methods, register them with Resonate, and it handles retries, recovery, and replay — when a process crashes mid-workflow, execution resumes from the last checkpoint instead of starting over. The SDK requires Java 21 or newer: it drives durable executions on virtual threads, a feature generally available as of Java 21, so Java 8, 11, and 17 are not supported.
- Open an issue or pull request — contribution starts here while the SDK is prerelease
- Evaluate Resonate for your next project
- Example application library — including the
-javastarter set - Distributed Async Await — the concepts that power Resonate
- Join the Discord
- Subscribe to the Journal
- Follow on X
- Follow on LinkedIn
- Subscribe on YouTube
- Install the Resonate Server & CLI
brew install resonatehq/tap/resonate- Add the SDK to your build
The SDK is published to Maven Central as io.resonatehq:resonate-sdk-java and requires Java 21+. These files go in a Gradle project — starting from scratch, gradle init scaffolds the layout, the settings.gradle.kts, and the ./gradlew wrapper that step 5 uses. With Gradle (Kotlin DSL):
// build.gradle.kts
plugins {
application
}
repositories {
mavenCentral()
}
dependencies {
implementation("io.resonatehq:resonate-sdk-java:0.1.1")
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
application {
mainClass = "myapp.Main"
}Using Maven instead? The coordinates are the same:
<dependency>
<groupId>io.resonatehq</groupId>
<artifactId>resonate-sdk-java</artifactId>
<version>0.1.1</version>
</dependency>Jackson (com.fasterxml.jackson.core:jackson-databind) comes in transitively for the JSON durability boundary — nothing extra to declare.
- Write your first Resonate function
Create src/main/java/myapp/Main.java. greet runs as a durable workflow: it calls a leaf function through ctx.run, and Resonate records that call as a durable child so a crash resumes from the checkpoint rather than re-running from the top.
// src/main/java/myapp/Main.java
package myapp;
import io.resonatehq.resonate.Context;
import io.resonatehq.resonate.Handle.ResonateHandle;
import io.resonatehq.resonate.Resonate;
public final class Main {
// A leaf function: pure computation, no durable op.
public static String formatGreeting(Context ctx, String name) {
return "hello, " + name + "!";
}
// A workflow: Resonate records the formatGreeting call as a durable child,
// so a crash mid-run resumes from the checkpoint instead of starting over.
public static String greet(Context ctx, String name) {
return ctx.run(Main::formatGreeting, name).await();
}
public static void main(String[] args) {
Resonate r = Resonate.builder().url("http://localhost:8001").build();
r.register(Main::greet);
try {
String id = "greet-" + System.nanoTime();
ResonateHandle<String> handle = r.run(id, Main::greet, "world");
System.out.println(id + " -> " + handle.result());
} finally {
r.stop();
}
}
}The SDK ships runnable example programs — hello-world, pipeline, saga, human-in-the-loop, retries, and more — under src/examples.
- Start the server (leave it running in its own terminal)
resonate dev- Run the program
./gradlew runThis one process does two jobs: register makes it a worker that can execute greet, and r.run(...) invokes the workflow and awaits the result.
Result
You'll see the durable promise ID and the greeting once the workflow settles:
greet-1784461234567890 -> hello, world!
What to try
- Inspect the durable promise the workflow created with
resonate promises get <id>(the ID is thegreet-...value printed in step 5). - Visualize the call graph with
resonate tree <id>— you'll see thegreetworkflow and itsformatGreetingchild. - Replace
"greet-" + System.nanoTime()with a fixed ID and run twice. The second run returns the recorded result instead of re-executing the workflow — durability is keyed by the promise ID.
Read the docs for the full programming model, the Context API, retry policies, and deployment patterns. A Java-specific skill guide (develop/java) is landing on the docs site; until it goes live, the src/examples programs in this repo and the Python SDK — whose API the Java SDK mirrors — are the closest reference.
Apache-2.0 — see LICENSE.