> ## Documentation Index
> Fetch the complete documentation index at: https://docs.restate.dev/llms.txt
> Use this file to discover all available pages before exploring further.

<AgentInstructions>

## Submitting Feedback

If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback:

POST https://docs.restate.dev/feedback

```json
{
  "path": "/changelog/java-kotlin-sdk",
  "feedback": "Description of the issue"
}
```

Only submit feedback when you have something specific and actionable to report.

</AgentInstructions>

# Java/Kotlin SDK changelog

> Releases of the Java/Kotlin SDK.

<Update label="2026-02-03" description="Java/Kotlin SDK v2.6.0">
  ### Release 2.6.0

  We're excited to announce Restate Java SDK 2.6.0!

  ### Virtual Threads by default (Java 21+)

  The default executor for Java services now uses virtual threads on Java 21+, falling back to `Executors.newCachedThreadPool()` for older Java versions.

  You can still customize the executor providing `HandlerRunner.Options.withExecutor()` to `Endpoint#bind`, or for Spring users, use the new Spring properties (`restate.executor` or `restate.components.&lt;name&gt;.executor`).

  **Note:** This change only applies to Java services. Kotlin services continue to `Dispatchers.Default` as default coroutine dispatcher.

  ### \[Spring Boot] Configure services using Spring's Properties

  You can now configure Restate services directly from Spring's `application.properties` or `application.yml` files. This provides a centralized way to configure service behavior without modifying code.

  ### Example Configuration

  ```properties theme={null}
  # Global executor for all services (Java only)
  restate.executor=myExecutorBean

  # Configuration for a service named "MyService"
  restate.components.MyService.executor=myServiceExecutor
  restate.components.MyService.inactivity-timeout=10m
  restate.components.MyService.abort-timeout=1m
  restate.components.MyService.idempotency-retention=7d
  restate.components.MyService.journal-retention=1d
  restate.components.MyService.ingress-private=false
  restate.components.MyService.enable-lazy-state=true
  restate.components.MyService.documentation=My service description
  restate.components.MyService.metadata.version=1.0
  restate.components.MyService.metadata.team=platform
  restate.components.MyService.retry-policy.initial-interval=100ms
  restate.components.MyService.retry-policy.exponentiation-factor=2.0
  restate.components.MyService.retry-policy.max-interval=10s
  restate.components.MyService.retry-policy.max-attempts=10
  restate.components.MyService.retry-policy.on-max-attempts=PAUSE

  # Per-handler configuration
  restate.components.MyService.handlers.myHandler.inactivity-timeout=5m
  restate.components.MyService.handlers.myHandler.ingress-private=true
  restate.components.MyService.handlers.myHandler.documentation=Handler description
  restate.components.MyService.handlers.myWorkflowHandler.workflow-retention=30d
  ```

  ### Annotation based configuration

  The `configuration` attribute on `@RestateService`, `@RestateVirtualObject`, and `@RestateWorkflow` annotations now accepts a bean name of type `RestateComponentProperties` (previously `RestateServiceConfigurator`):

  ```java theme={null}
  @RestateService(configuration = "myServiceConfig")
  public class MyService {
      // ...
  }

  @Bean
  public RestateComponentProperties myServiceConfig() {
      return new RestateComponentProperties()
          .setInactivityTimeout(Duration.ofMinutes(10))
          .setDocumentation("My service");
  }
  ```

  ### \[Kotlin] New experimental API

  Following the introduction of the new experimental API for Java in v2.5.0, we're now bringing the same experience to Kotlin!

  The new API **removes the need for the KSP code generator**, making it significantly simpler to use the Restate SDK:

  * **No KSP code generator required**: The SDK now uses reflection to discover and bind your services, eliminating the need for build-time code generation and making your build simpler and faster.
  * **No more Context parameters**: Handler methods no longer need to accept a `Context` parameter. Instead, use top-level functions from `dev.restate.sdk.kotlin` to access state, promises, and other Restate functionality.
  * **Cleaner method signatures**: Your handler methods now have cleaner signatures that focus on your business logic rather than Restate infrastructure.

  The new API is **opt-in** and can be incrementally adopted in an existing project, meaning the existing API will continue to work as usual.
  It is marked as **experimental** and subject to change in the next releases.

  We're looking for **your feedback** to evolve it and stabilize it!

  ### How to use it

  1. Remove the KSP code generator dependency `sdk-api-kotlin-gen`

  2. Remove the `Context`, `ObjectContext`, `SharedObjectContext`, `WorkflowContext`, `SharedWorkflowContext` parameters from your `@Handler` annotated methods. For example:

     ```kotlin theme={null}
     @VirtualObject
     class Counter {

       @Handler
       suspend fun add(ctx: ObjectContext, value: Long) {}

       @Shared
       @Handler
       suspend fun get(ctx: SharedObjectContext): Long {}
     }
     ```

     Becomes:

     ```kotlin theme={null}
     import dev.restate.sdk.kotlin.*

     @VirtualObject
     class Counter {

       @Handler
       suspend fun add(value: Long) {}

       @Shared
       @Handler
       suspend fun get(): Long {}
     }
     ```

     The same applies for interfaces using Restate annotations.

  3. Replace all the usages of `ctx.` with the top-level functions. For example:

     ```kotlin theme={null}
     @Handler
     suspend fun add(ctx: ObjectContext, value: Long) {
         val currentValue = ctx.get(TOTAL) ?: 0L
         val newValue = currentValue + value
         ctx.set(TOTAL, newValue)
     }
     ```

     Becomes:

     ```kotlin theme={null}
     @Handler
     suspend fun add(value: Long) {
         val state = state()
         val currentValue = state.get(TOTAL) ?: 0L
         val newValue = currentValue + value
         state.set(TOTAL, newValue)
     }
     ```

  4. Replace all the usages of code-generated clients. There are two ways to invoke services:

     **Simple proxy (for direct calls):**

     The top-level functions let you create proxies to call services directly using `service&lt;T&gt;()`, `virtualObject&lt;T&gt;(key)` and `workflow&lt;T&gt;(key)`:

     ```kotlin theme={null}
     virtualObject<Counter>("my-key").add(1) // Direct method call
     ```

     **Handle-based (for advanced patterns):**

     For asynchronous handling, request composition, or invocation options (such as idempotency keys), use `toService&lt;T&gt;()`, `toVirtualObject&lt;T&gt;(key)` and `toWorkflow&lt;T&gt;(key)`:

     ```kotlin theme={null}
     // Use call() with a lambda to return a DurableFuture you can await asynchronously and/or compose with other futures
     val count = toVirtualObject<Counter>("my-counter")
         .request { add(1) }
         .call()
         .await()

     // Use send() for one-way invocation without waiting
     val handle = toVirtualObject<Counter>("my-counter")
         .request { add(1) }
         .send()

     // Add request options such as idempotency key
     val count = toVirtualObject<Counter>("my-counter")
         .request { add(1) }
         .options { idempotencyKey = "my-idempotency-key" }
         .call()
         .await()
     ```

  ### Reference sheet

  | `Context` API (2.5.x)                                             | New reflection API (2.6.0)                                      |
  | ----------------------------------------------------------------- | --------------------------------------------------------------- |
  | `ctx.runBlock &#123; ... &#125;`/`ctx.runAsync &#123; ... &#125;` | `runBlock &#123; ... &#125;`/`runAsync &#123; ... &#125;`       |
  | `ctx.random()`                                                    | `random()`                                                      |
  | `ctx.timer()`                                                     | `timer()`                                                       |
  | `ctx.awakeable()`                                                 | `awakeable&lt;T&gt;()`                                          |
  | `ctx.get(key)` / `ctx.set(key, value)`                            | `state().get(key)` / `state().set(key, value)`                  |
  | `ctx.promise(key)`                                                | `promise(key)`                                                  |
  | Code generated clients (Services)                                 | `service&lt;T&gt;()` / `toService&lt;T&gt;()`                   |
  | Code generated clients (Virtual Objects)                          | `virtualObject&lt;T&gt;(key)` / `toVirtualObject&lt;T&gt;(key)` |
  | Code generated clients (Workflows)                                | `workflow&lt;T&gt;(key)` / `toWorkflow&lt;T&gt;(key)`           |

  ### Using concrete classes with proxy clients

  By default, Kotlin classes are `final`, preventing libraries like Restate to generate runtime client proxies.

  We generally suggest one of the following three options:

  * Define an interface with all Restate annotations and have your class implement it. Use the interface type for proxy calls, e.g. `service&lt;MyServiceInterface&gt;()`.
  * Use `open` in all Restate annotated classes/methods.
  * Setup the [Kotlin allopen compiler plugin](https://kotlinlang.org/docs/all-open-plugin.html) with the following configuration:

  **Gradle (Kotlin DSL)**

  ```kotlin theme={null}
  plugins {
      kotlin("plugin.allopen") version "<kotlin-version>"
  }

  allOpen {
      annotations("dev.restate.sdk.annotation.Service", "dev.restate.sdk.annotation.VirtualObject", "dev.restate.sdk.annotation.Workflow")
  }
  ```

  This configuration automatically makes any class annotated with Restate annotations open, along with all their methods.

  ### Gradual migration

  You can gradually migrate to the new API by disabling the KSP code generator for specific classes.
  For example, if you have a project with a `my.example.Greeter` and a `my.example.Counter`, you can decide to migrate only `my.example.Counter` to use the new API.

  To do so, keep the KSP code generator dependency and pass the KSP option `dev.restate.codegen.disabledClasses` as follows:

  **Gradle (Kotlin DSL)**

  ```kotlin theme={null}
  ksp {
    val disabledClassesCodegen =
      listOf(
        // Ignore Counter in the KSP code generator
        "my.example.Counter")

    arg("dev.restate.codegen.disabledClasses", disabledClassesCodegen.joinToString(","))
  }
  ```

  ### New API for Deterministic Time

  We've added a new API to get the current time deterministically that's consistent across replays.

  ### Java

  ```java theme={null}
  import java.time.Instant;

  @Handler
  public String myHandler() {
      Instant now = Restate.instantNow();
      // or using the context-based API:
      // Instant now = ctx.instantNow();
      return "Current time: " + now;
  }
  ```

  ### Kotlin

  ```kotlin theme={null}
  import kotlin.time.Clock
  import kotlin.time.ExperimentalTime
  import dev.restate.sdk.kotlin.*

  @OptIn(ExperimentalTime::class)
  @Handler
  suspend fun myHandler(): String {
      val now = Clock.Restate.now()
      return "Current time: $now"
  }
  ```

  Note: in Kotlin you need to opt in the [Kotlin experimental time APIs](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.time/-experimental-time/).

  ### Other changes

  * Fix detection of `@Raw` annotation in Java Reflection API
  * `Serde.RAW.contentType()` now correctly returns `application/octet-stream`
  * Dependency updates:
    * Jackson 2.19.4
    * Spring Boot 3.4.13
    * Vert.x 4.5.24
    * OpenTelemetry 1.58.0
    * JUnit 5.14.1

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v2.6.0)
</Update>

<Update label="2026-01-13" description="Java/Kotlin SDK v2.5.0">
  ### Release 2.5.0

  We're excited to announce Restate Java SDK 2.5.0, featuring a major improvement to the developer experience with a new **reflection-based API**.

  ### Experimental Reflection-Based API

  The new reflection-based API **removes the need for the annotation processor**, making it significantly simpler to use the Restate SDK:

  * **No annotation processor required**: The SDK now uses reflection to discover and bind your services, eliminating the need for build-time annotation processing and making your build simpler and faster.
  * **No more Context parameters**: Handler methods no longer need to accept a `Context` parameter. Instead, use static methods from the `Restate` class to access state, promises, and other Restate functionality.
  * **Cleaner method signatures**: Your handler methods now have cleaner signatures that focus on your business logic rather than Restate infrastructure.

  The new API is **opt-in** and can be incrementally adopted in an existing project, meaning the existing API will continue to work as usual.
  It is marked as **experimental** and subject to change in the next releases.

  This API is currently available only for **Java**, but we plan to add an equivalent for **Kotlin** in future releases.

  We're looking for **your feedback** to evolve it and stabilize it!

  ### How to use it

  1. Remove the annotation processor dependency `sdk-api-gen`

  2. Remove the `Context`, `ObjectContext`, `SharedObjectContext`, `WorkflowContext`, `SharedWorkflowContext` parameters from your `@Handler` annotated methods. For example:

     ```java theme={null}
     @VirtualObject
     public class Counter {

       @Handler
       public void add(ObjectContext ctx, long request) {}

       @Shared
       @Handler
       public long get(SharedObjectContext ctx) {}
     }
     ```

     Becomes:

     ```java theme={null}
     @VirtualObject
     public class Counter {

       @Handler
       public void add(long request) {}

       @Shared
       @Handler
       public long get() {}
     }
     ```

     The same applies for interfaces using Restate annotations.

  3. Replace all the usages of `ctx.` with `Restate.`. For example:

     ```java theme={null}
     @Handler
     public void add(ObjectContext ctx, long value) {
         long currentValue = ctx.get(TOTAL).orElse(0L);
         long newValue = currentValue + value;
         ctx.set(TOTAL, newValue);
     }
     ```

     Becomes:

     ```java theme={null}
     @Handler
     public void add(long value) {
         var state = Restate.state();
         long currentValue = state.get(TOTAL).orElse(0L);
         long newValue = currentValue + value;
         state.set(TOTAL, newValue);
     }
     ```

  4. Replace all the usages of code-generated clients. There are two ways to invoke services:

     **Simple proxy (for direct calls):**

     The `Restate` class lets you create proxies to call services directly using `service(Class)`, `virtualObject(Class, key)` and `workflow(Class, key)`:

     ```java theme={null}
     Restate.virtualObject(Counter.class, "my-key").add(1); // Direct method call
     ```

     **Handle-based (for advanced patterns):**

     For asynchronous handling, request composition, or invocation options (such as idempotency keys), use `serviceHandle(Class)`, `virtualObjectHandle(Class, key)` and `workflowHandle(Class, key)`:

     ```java theme={null}
     // Use call() with method reference to return a DurableFuture you can await asynchronously and/or compose with other futures
     int count = Restate.virtualObjectHandle(Counter.class, "my-counter")
         .call(Counter::increment)
         .await();

     // Use send() for one-way invocation without waiting
     InvocationHandle<Integer> handle = Restate.virtualObjectHandle(Counter.class, "my-counter")
         .send(Counter::increment);

     // Add request options such as idempotency key
     int count = Restate.virtualObjectHandle(Counter.class, "my-counter")
             .call(Counter::increment, InvocationOptions.idempotencyKey("my-idempotency-key"))
             .await();
     ```

  ### Reference sheet

  | `Context` API (2.4.x)                    | New `Restate` API (2.5.0)                                                       |
  | ---------------------------------------- | ------------------------------------------------------------------------------- |
  | `ctx.run(...)`                           | `Restate.run(...)`                                                              |
  | `ctx.random()`                           | `Restate.random()`                                                              |
  | `ctx.timer()`                            | `Restate.timer()`                                                               |
  | `ctx.awakeable()`                        | `Restate.awakeable()`                                                           |
  | `ctx.get(key)` / `ctx.set(key, value)`   | `Restate.state().get(key)` / `Restate.state().set(key, value)`                  |
  | `ctx.promise(key)`                       | `Restate.promise(key)`                                                          |
  | Code generated clients (Services)        | `Restate.service(Class)` / `Restate.serviceHandle(Class)`                       |
  | Code generated clients (Virtual Objects) | `Restate.virtualObject(Class, key)` / `Restate.virtualObjectHandle(Class, key)` |
  | Code generated clients (Workflows)       | `Restate.workflow(Class, key)` / `Restate.workflowHandle(Class, key)`           |

  ### Gradual migration

  You can gradually migrate to the new API by disabling the annotation processor for specific classes.
  For example, if you have a project with a `my.example.Greeter` and a `my.example.Counter`, you can decide to migrate only `my.example.Counter` to use the new API.

  To do so, keep the annotation processor dependency and pass the compiler option `dev.restate.codegen.disabledClasses` as follows:

  **Gradle**

  ```kotlin theme={null}
  tasks.withType<JavaCompile> {
    val disabledClassesCodegen =
      listOf(
        // Ignore Counter in the annotation processor
        "my.example.Counter")

    options.compilerArgs.addAll(
      listOf(
        "-Adev.restate.codegen.disabledClasses=${disabledClassesCodegen.joinToString(",")}",
      ))
  }
  ```

  **Maven**

  ```xml theme={null}
  <build>
      <plugins>
        <!-- Setup annotation processor -->
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.11.0</version>
          <configuration>
            <annotationProcessorPaths>
              <path>
                <groupId>dev.restate</groupId>
                <artifactId>sdk-api-gen</artifactId>
                <version>${restate.version}</version>
              </path>
            </annotationProcessorPaths>
            <compilerArgs>
              <!-- Ignore Counter in the annotation processor -->
              <arg>-Adev.restate.codegen.disabledClasses=my.example.Counter</arg>
            </compilerArgs>
          </configuration>
        </plugin>
      </plugins>
  </build>
  ```

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v2.5.0)
</Update>

<Update label="2025-12-09" description="Java/Kotlin SDK v2.4.2">
  ### What's Changed

  * Various improvements to the code generator

  ### New Contributors

  * @muhamadazmy made their first contribution in [https://github.com/restatedev/sdk-java/pull/562](https://github.com/restatedev/sdk-java/pull/562)
  * @squarepegg made their first contribution in [https://github.com/restatedev/sdk-java/pull/563](https://github.com/restatedev/sdk-java/pull/563)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v2.4.2)
</Update>

<Update label="2025-11-03" description="Java/Kotlin SDK v2.4.1">
  ### Notable changes

  * Fix bug in the state machine that caused, in some cases, the invocation to hang when inactivity timeout kicked in. [https://github.com/restatedev/sdk-java/pull/556](https://github.com/restatedev/sdk-java/pull/556)
  * bump handlebars dependency from 4.3.1 to 4.5.0 by @djarnis73 in [https://github.com/restatedev/sdk-java/pull/557](https://github.com/restatedev/sdk-java/pull/557)

  ### New Contributors

  * @djarnis73 made their first contribution in [https://github.com/restatedev/sdk-java/pull/557](https://github.com/restatedev/sdk-java/pull/557)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v2.4.1)
</Update>

<Update label="2025-09-16" description="Java/Kotlin SDK v2.4.0">
  ### Invocation retry policy

  When used with Restate 1.5, you can now configure the invocation retry policy from the SDK directly. See [https://github.com/restatedev/restate/releases/tag/v1.5.0](https://github.com/restatedev/restate/releases/tag/v1.5.0) for more details on the new invocation retry policy configuration.

  ### \[Spring integration] Configure service options

  A new API was introduced to configure services using the Spring integration:

  ```java theme={null}
  // Specifiy the bean name of the configuration
  @RestateService(configuration = "greeterConfiguration")
  public class Greeter {
    // Your service
  }

  // Example configuration class
  public class Configuration {
    @Bean
    public RestateServiceConfigurator greeterConfiguration() {
      return configurator -> configurator.inactivityTimeout(Duration.ofMinutes(2));
    }
  }
  ```

  ### What's Changed

  * \[Release] Bump to 2.4.0-SNAPSHOT by @github-actions\[bot] in [https://github.com/restatedev/sdk-java/pull/531](https://github.com/restatedev/sdk-java/pull/531)
  * Bump org.assertj:assertj-core from 3.26.0 to 3.27.4 by @dependabot\[bot] in [https://github.com/restatedev/sdk-java/pull/536](https://github.com/restatedev/sdk-java/pull/536)
  * Retry policy by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/540](https://github.com/restatedev/sdk-java/pull/540)
  * Protocol V6 + random\_seed support by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/542](https://github.com/restatedev/sdk-java/pull/542)
  * Test Suite v3.1 by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/545](https://github.com/restatedev/sdk-java/pull/545)
  * Clarify max attempts meaning by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/546](https://github.com/restatedev/sdk-java/pull/546)
  * Add workflow retention setting at service level by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/547](https://github.com/restatedev/sdk-java/pull/547)
  * Add entrypoint to setup a configurator for Spring Restate services. by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/548](https://github.com/restatedev/sdk-java/pull/548)
  * Dependency bumps by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/549](https://github.com/restatedev/sdk-java/pull/549)
  * \[Release] Bump to 2.4.0 by @github-actions\[bot] in [https://github.com/restatedev/sdk-java/pull/550](https://github.com/restatedev/sdk-java/pull/550)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v2.4.0)
</Update>

<Update label="2025-08-18" description="Java/Kotlin SDK v2.3.0">
  **IMPORTANT For Spring Users**: Due to [MadeYourReset CVE](https://kb.cert.org/vuls/id/767506), we bumped Vert.x and Netty to latest releases. This results in misaligned Netty dependency when used in combination with Spring Parent POM/Gradle dependency management plugin. To fix it, force the correct Netty version:

  * If you use Maven with spring parent POM add `<netty.version>4.1.124.Final</netty.version>`  to your POM
  * If you use Gradle Spring dependency management plugin add `netty.version = 4.1.124.Final` to the `gradle.properties` file

  ### Improvements

  * Added ability to disable bidirectional streaming. This can be useful in some environments where HTTP/2 streaming doesn't work properly. To disable it using `RestateHttpServer`:

  ```java theme={null}
  var handler = HttpEndpointRequestHandler.fromEndpoint(
        Endpoint.builder().bind(new Counter()).build(),
        /* disableBidirectionalStreaming */ true
  );
  RestateHttpServer.listen(handler);
  ```

  To disable it when using the spring boot integration, add `restate.sdk.http.disableBidirectionalStreaming=true` to your `application.properties`

  * Add `delay` to generated workflow clients `submit` method
  * Added few extension methods to Kotlin ingress client

  ### Bug fixes

  * Removed double logging of `TerminalException`
  * Removed noisy logging of coroutine cancellation when irrelevant
  * Dependency bumps
    * Vert.x 4.5.18
    * Kotlin 2.2.10

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v2.3.0)
</Update>

<Update label="2025-08-06" description="Java/Kotlin SDK v2.2.1">
  ### What's Changed

  * \[Release] Bump to 2.3.0-SNAPSHOT by @github-actions\[bot] in [https://github.com/restatedev/sdk-java/pull/512](https://github.com/restatedev/sdk-java/pull/512)
  * Few improvements to errors from sdk-shared-core by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/513](https://github.com/restatedev/sdk-java/pull/513)
  * Improve formatting of journal mismatch by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/514](https://github.com/restatedev/sdk-java/pull/514)
  * Fix usage of filer/classloader for resources. by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/517](https://github.com/restatedev/sdk-java/pull/517)
  * Add commandIndex to mismatch exceptions by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/518](https://github.com/restatedev/sdk-java/pull/518)
  * \[Release] Bump to 2.2.1 by @github-actions\[bot] in [https://github.com/restatedev/sdk-java/pull/519](https://github.com/restatedev/sdk-java/pull/519)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v2.2.1)
</Update>

<Update label="2025-07-03" description="Java/Kotlin SDK v2.2.0">
  * You can now configure the service/handler options when binding the services, e.g. in Kotlin:

  ```kotlin theme={null}
  endpoint {
    bind(MyService()) {
      it.journalRetention = 10.days
      it.configureHandler("myHandler") {
        it.inactivityTimeout = 10.minutes
      }
    }
  }
  ```

  * The following new configuration options are available for services and handlers: `inactivityTimeout`, `abortTimeout`, `idempotencyRetention`, `journalRetention`, `ingressPrivate`, `enableLazyState`. Please note, these will only work with Restate 1.4 onward.

  ### What's Changed

  * \[Release] Bump to 2.2.0-SNAPSHOT by @github-actions in [https://github.com/restatedev/sdk-java/pull/506](https://github.com/restatedev/sdk-java/pull/506)
  * Endpoint manifest V3 by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/508](https://github.com/restatedev/sdk-java/pull/508)
  * Dep updates for security by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/509](https://github.com/restatedev/sdk-java/pull/509)
  * Update coordinates for the new publishing portal by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/510](https://github.com/restatedev/sdk-java/pull/510)
  * \[Release] Bump to 2.2.0 by @github-actions in [https://github.com/restatedev/sdk-java/pull/511](https://github.com/restatedev/sdk-java/pull/511)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v2.2.0)
</Update>

<Update label="2025-06-05" description="Java/Kotlin SDK v2.1.1">
  ### What's Changed

  * \[Release] Bump to 2.2.0-SNAPSHOT by @github-actions in [https://github.com/restatedev/sdk-java/pull/500](https://github.com/restatedev/sdk-java/pull/500)
  * Make KtTypeTag public by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/504](https://github.com/restatedev/sdk-java/pull/504)
  * \[Release] Bump to 2.1.1 by @github-actions in [https://github.com/restatedev/sdk-java/pull/505](https://github.com/restatedev/sdk-java/pull/505)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v2.1.1)
</Update>

<Update label="2025-04-29" description="Java/Kotlin SDK v2.1.0">
  ### What's Changed

  ### Kotlin now supports JSON Schema

  The Kotlin API now supports OOTB generating Json Schemas, using [https://github.com/SMILEY4/schema-kenerator](https://github.com/SMILEY4/schema-kenerator). The schemas will be automatically propagated to `restate-server`, and they will be available in the generated [OpenAPI](https://docs.restate.dev/invoke/http/#openapi-support) and in the Restate Playground.

  ### Changelog

  * \[Release] Bump to 2.1.0-SNAPSHOT by @github-actions in [https://github.com/restatedev/sdk-java/pull/493](https://github.com/restatedev/sdk-java/pull/493)
  * Fix ktdocs for select and awaitAll by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/494](https://github.com/restatedev/sdk-java/pull/494)
  * Generate Json Schemas for Kotlin by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/495](https://github.com/restatedev/sdk-java/pull/495)
  * Fix #497 by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/498](https://github.com/restatedev/sdk-java/pull/498)
  * \[Release] Bump to 2.1.0 by @github-actions in [https://github.com/restatedev/sdk-java/pull/499](https://github.com/restatedev/sdk-java/pull/499)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v2.1.0)
</Update>

<Update label="2025-04-10" description="Java/Kotlin SDK v2.0.0">
  ### Java/Kotlin SDK 2.0

  We're pleased to announce the release of Java/Kotlin SDK 2.0, in combination with Restate 1.3.
  Check out the announcement blog post for more details about Restate 1.3 and the new SDK features: [https://restate.dev/blog/announcing-restate-1.3/](https://restate.dev/blog/announcing-restate-1.3/)

  Below are the changes specific to the Java/Kotlin SDK.

  ### What's new and what changed

  ### New meta packages

  From now on you don't need to pick individual packages of the SDK to get started, but you can use the new meta packages:

  * `dev.restate:sdk-java-http` for Java API + HTTP endpoint (example [`build.gradle.kts`](https://github.com/restatedev/examples/blob/6eb81f3657d785ca67cc594522d4d567461c7ce9/java/templates/java-gradle/build.gradle.kts)/[`pom.xml`](https://github.com/restatedev/examples/blob/6eb81f3657d785ca67cc594522d4d567461c7ce9/java/templates/java-maven/pom.xml))
  * `dev.restate:sdk-java-lambda` for Java API + Lambda endpoint
  * `dev.restate:sdk-kotlin-http` for Kotlin API + HTTP endpoint (example [`build.gradle.kts`](https://github.com/restatedev/examples/blob/6eb81f3657d785ca67cc594522d4d567461c7ce9/kotlin/templates/kotlin-gradle/build.gradle.kts))
  * `dev.restate:sdk-kotlin-lambda` for Kotlin API + Lambda endpoint

  E.g. for Java (gradle):

  ```kotlin theme={null}
  annotationProcessor("dev.restate:sdk-api-gen:2.0.0")

  // Java API + HTTP endpoint
  implementation("dev.restate:sdk-java-http:2.0.0")
  ```

  For kotlin:

  ```kotlin theme={null}
  // Code generator
  ksp("dev.restate:sdk-api-kotlin-gen:2.0.0")

  // Kotlin API + HTTP endpoint
  implementation("dev.restate:sdk-kotlin-http:2.0.0")
  ```

  You still need to individually import the code generator packages, as before, because those are not required at runtime.

  ### Code generation and sharing code-generated artifacts

  We made few changes to the generated code, with the goal of simplifying sharing code generated artifacts with 3rd party consumers of your Restate services.

  Among the notable breaking changes:

  * All methods in generated clients, both for normal client and `Context` client, have an overload/optional parameter that allows to set additional options, including headers and `idempotencyKey` to use. **Removed** the old overloads accepting `CallRequestOptions`. For example this code:

  ```java theme={null}
  client.handler("input", CallRequestOptions.DEFAULT.withIdempotency("my key"))
  ```

  becomes

  ```java theme={null}
  client.handler("input", opts -> opts.idempotencyKey("my key"))
  ```

  * Annotations `@Service`/`@VirtualObject`/`@Workflow` `name` argument is deprecated, you can now override the name used by Restate for both services and handlers using the `@Name` annotation. This name **won't affect anymore** the name prefix of the generated classes.
  * The clients method `.send(Duration)` has been removed in favor of overloads/optional parameter to perform one way calls with `delay`.
  * The new class `[your service name]Handlers` contains inside the old class `[your service name]Metadata`.
  * All send methods in context clients now return `InvocationHandle`.

  A new class will now be generated, called `[your service name]Handlers`, that lets you easily call your service as follows:

  ```kotlin theme={null}
  // For service to service
  GreeterHandlers.greet(request).call(ctx)
  GreeterHandlers.greet(request).send(ctx)

  // For Client
  val restateClient: Client = Client.connect("https://my-restate/")
  GreeterHandlers.greet(request).call(restateClient)
  GreeterHandlers.greet(request).send(restateClient)
  ```

  This class has few dependencies on some core classes of the SDK, that we commit to maintain ABI stable.
  You can publish/share this generated class, and use it in combination with the `Client` simply importing the module `dev.restate:client` for Java or `dev.restate:client-kotlin` for Kotlin.

  On top of that, this class works both for Kotlin API users and with Java API users, letting you call from Java to Kotlin and vice versa.

  If you don't use the `[...]Client` class, but you use only the `[...]Handlers`, we suggest disabling its code generation as follows. For Java (gradle):

  ```kotlin theme={null}
  tasks {
    withType<JavaCompile> {
      options.compilerArgs.addAll(
        listOf(
          "-Adev.restate.codegen.disabledClientGeneration=my.fqcn.ServiceName"
        )
      )
    }
  }
  ```

  In Kotlin KSP (gradle):

  ```kotlin theme={null}
  ksp {
    arg("dev.restate.codegen.disabledClientGeneration", "my.fqcn.ServiceName")
  }
  ```

  Note: the generated artifacts from the SDK 1.x versions **ARE NOT** compatible with the generated artifacts from 2.x onward.
  From SDK 2.x, we commit to a stable ABI between generated code artifacts and the SDK versions, meaning you'll be able to safely mix code generated artifacts with SDK version. For example, you'll be able to import a code generated artifact using SDK 2.0 in a project using SDK 2.1.

  ### `Client` changes

  We overhauled the client to interact with Restate. Now it lives in a new maven module ad hoc called `dev.restate:client`, which you can import separately from the rest of the SDK when you need to interact only with Restate from another Java/Kotlin application.

  Notable changes:

  * **Renamed** package `dev.restate.sdk.client` to `dev.restate.client`
  * **Renamed** `dev.restate.sdk.client.CallRequestOptions` to `dev.restate.client.RequestOptions`
  * Now all client methods returns headers and status code, see interface `dev.restate.client.ResponseHead`.
  * It is possible to bootstrap your own `Client` implementation using the HTTP client of your choice extending `dev.restate.client.base.BaseClient`

  ### `Endpoint` and `RestateHttpServer`

  We now expose a uniform API across Http and Lambda support to build your service endpoint. In Java:

  ```java theme={null}
  var endpoint = Endpoint
          .bind(new Greeter())
          // Run Counter on virtual threads
          .bind(new Counter(), HandlerRunner.Options.withExecutor(Executors.newVirtualThreadPerTaskExecutor()));

  // E.g. bind to server
  RestateHttpServer.listen(endpoint);
  ```

  In Kotlin:

  ```kotlin theme={null}
  val endpoint = endpoint {
    bind(Greeter())
    // Decorate the coroutine context used by the handler
    bind(Counter(), HandlerRunner.Options(Dispatchers.Default + CoroutineName("counter")))
  }

  // E.g. bind to server
  RestateHttpServer.listen(endpoint)
  ```

  Using `HttpEndpointRequestHandler.fromEndpoint(Endpoint)` it is also possible to get a Vert.x request handler for your endpoint, that can be used to build the HTTP server manually.

  Notable changes:

  * `RestateHttpEndpointBuilder` was deprecated, use `RestateHttpServer` instead.
  * `RestateLambdaEndpointBuilder` was removed, now `BaseRestateLambdaHandler.register` takes `Endpoint.Builder` as argument.

  ### The `DurableFuture` interface

  We renamed the `Awaitable` to `DurableFuture` and reworked few of its methods, to make it easier to interact with asynchronous events and compose them:

  * Added `DurableFuture.withTimeout(Duration)` to return a future composed with the timeout. This has the same behavior as `DurableFuture.await(Duration)` but it returns a future that can be later awaited, instead of awaiting the future immediately.
  * `DurableFuture.await(Duration)` now throws `dev.restate.sdk.common.TimeoutException` instead of `java.util.concurrent.TimeoutException`.
  * Added `DurableFuture.map(successMapper)`, `DurableFuture.map(successMapper, failureMapper)` and `DurableFuture.mapFailure(failureMapper)`, to map futures result once completed.

  Check out the respective [`DurableFuture` Javadocs](https://docs.restate.dev/javadocs/dev/restate/sdk/DurableFuture)/[`DurableFuture` KotlinDocs](https://docs.restate.dev/ktdocs/sdk-api-kotlin/dev.restate.sdk.kotlin/-durable-future) for more details.

  ### Deterministic resilient concurrency

  As described in the [blog post](https://restate.dev/blog/announcing-restate-1.3/), Restate 1.3 improves support over deterministic concurrency.

  In Java we expose the new API [`Select`](https://docs.restate.dev/javadocs/dev/restate/sdk/Select) to await on multiple futures at the same time:

  ```java theme={null}
  DurableFuture<String> a12 = Select.<String>select()
          .or(a1)
          .or(a2);
  ```

  In Kotlin you can use the [`select`](https://docs.restate.dev/ktdocs/sdk-api-kotlin/dev.restate.sdk.kotlin/select) function, which now returns a `DurableFuture` itself and can be composed too:

  ```kotlin theme={null}
  select {
    a1.onAwait { it }
    a2.onAwait { it }
  }
  ```

  ### `ctx.runAsync` to compose asynchronous side effects

  Both in Java and Kotlin you can now use the `ctx.runAsync` API in order to execute a side effect, and return a `DurableFuture` instead than the result immediately. You can then compose this future with other `DurableFuture`s, for example to implement fan-in/fan-out operations.

  ### `InvocationHandle` for finer control over service-to-service communication

  As described in the [blog post](https://restate.dev/blog/announcing-restate-1.3/), Restate 1.3 features new APIs to interact with running invocations.

  All these features are encapsulated in the new `InvocationHandle`([Javadocs](https://docs.restate.dev/javadocs/dev/restate/sdk/InvocationHandle)/[Kotlin docs](https://docs.restate.dev/ktdocs/sdk-api-kotlin/dev.restate.sdk.kotlin/-invocation-handle/)) API:

  ```kotlin theme={null}
  val handle = GreeterClient.fromContext(context).send().greet(request)

  // Get invocation id
  val invocationId = handle.invocationId()

  // Cancel invocation
  handle.cancel()

  // Attach and await result
  val result = handle.attach().await()
  ```

  ### New `Serde` stack

  We overhauled the `Serde` stack completely. Now you don't need to pass around, neither figure out `Serde`s anymore, but you just need to focus on what types you need. For example:

  ```java theme={null}
  // Defining a state key
  StateKey<Integer> REMINDER_COUNT = StateKey.of("reminder_count", Integer.TYPE);

  // Using ctx.run
  String result = ctx.run(String.class, () -> doSideEffect());
  ```

  Or for generic types:

  ```java theme={null}
  List<SubTask> subTasks = ctx.run(new TypeRef<>() {}, () -> split(task));
  ```

  In Kotlin, defining state keys/durable promise keys is easier than ever:

  ```kotlin theme={null}
  val COUNT = stateKey<Int>("greet-count")
  ```

  By default, we still use Jackson for Java, and Kotlinx serialization for Kotlin, but you can completely override these choices by bringing in your serialization/deserialization stack.
  For this, and more details on how to customize the Jackson or Kotlinx serialization defaults, check this documentation page: [https://docs.restate.dev/develop/java/serialization](https://docs.restate.dev/develop/java/serialization)

  Notable changes:

  * Renamed `dev.restate.sdk.common.Serde` to `dev.restate.serde.Serde`
  * `JsonSerdes` is deprecated, use the `Class` and `TypeTag` overloads of `Context` methods instead. Check above how the new `Serde` stack works.
  * `KtSerdes`/`KtDurablePromiseKey`/`KtStateKey` are deprecated. To create a state key in Kotlin use `stateKey&lt;T&gt;(name)`, for a durable promise key `durablePromiseKey&lt;T&gt;(name)`. Check above how the new `Serde` stack works.
  * `Serde` interface now uses `dev.restate.common.Slice` instead of directly byte arrays/NIO `ByteBuffer`.

  ### Kotlin Spring Boot integration

  In the SDK release 1.2 we introduced an integration with Spring Boot, specifically designed for the Java API. We now introduced a similar integration in Kotlin too, to let you easily build Restate applications using Kotlin and Spring boot. Check out the quickstart: [https://docs.restate.dev/get\_started/quickstart?sdk=kotlin](https://docs.restate.dev/get_started/quickstart?sdk=kotlin)

  ### Other changes

  * SDK Java 2.0 works only with Restate 1.3 onward.
  * There is a new API to call/send requests between services, without using the client. Check out the [`dev.restate.common.Request` javadocs](https://docs.restate.dev/javadocs/dev/restate/common/Request) for more details.
  * `protobuf` is now distributed shaded, in order to avoid dependency conflicts.
  * Package `sdk-serde-protobuf` was removed.
  * Removed deprecations.

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v2.0.0)
</Update>

<Update label="2024-11-20" description="Java/Kotlin SDK v1.2.0">
  We're pleased to announce the release of the Java SDK 1.2.0

  ### New features

  * We now have a new Spring Boot to easily use the Restate SDK within your Spring Boot application. For more details, check out the example: [https://github.com/restatedev/examples/tree/main/templates/java-maven-spring-boot](https://github.com/restatedev/examples/tree/main/templates/java-maven-spring-boot)
  * The `sdk-testing` package has been revamped to a more friendly and easier to use API, you can check it out here [https://github.com/restatedev/examples/blob/9a9c7cf85c830f33a5f257db3ec986a09a1878b0/templates/java-gradle/src/test/java/my/example/GreeterTest.java](https://github.com/restatedev/examples/blob/9a9c7cf85c830f33a5f257db3ec986a09a1878b0/templates/java-gradle/src/test/java/my/example/GreeterTest.java). The old API is still available but it's now deprecated, and will be removed in subsequent releases.

  ### Notable changes

  * The `ctx.run` with `RetryPolicy` has been promoted to stable feature, check the [Javadocs](https://docs.restate.dev/javadocs/dev/restate/sdk/Context#run\(java.lang.String,dev.restate.sdk.common.Serde,dev.restate.sdk.common.RetryPolicy,dev.restate.sdk.common.function.ThrowingSupplier\)) for more details.
  * You can now use checked exceptions within your `@Handler` annotated methods.

  ### Breaking changes

  * Bumped minimum JDK version to 17
  * Because of a breaking change within log4j, you **MUST** either bump `log4j-core` to >= 2.24, or exclude the `log4j-api` dependency when depending on the SDK. For example, in gradle:

  ```
  // Restate SDK
  implementation("dev.restate:sdk-api:$restateVersion") {
     // Exclude transitive deps on log4j2
    exclude(group = "org.apache.logging.log4j")
  }
  implementation("dev.restate:sdk-http-vertx:$restateVersion") {
    exclude(group = "org.apache.logging.log4j")
  }
  // To use Jackson to read/write state entries (optional)
  implementation("dev.restate:sdk-serde-jackson:$restateVersion") {
    exclude(group = "org.apache.logging.log4j")
  }

  // Pin log4j2 to 2.20
  implementation("org.apache.logging.log4j:log4j-core:2.20.0")
  implementation("org.apache.logging.log4j:log4j-api:2.20.0") 
  ```

  * This release is not bytecode compatible with previous releases, meaning you can't mix the annotation processor generated code from SDK \<= 1.2.0 with this release.
  * This release is compatible with Restate >= 1.1

  ### Changelog

  * \[Release] Bump to 1.2.0-SNAPSHOT by @github-actions in [https://github.com/restatedev/sdk-java/pull/383](https://github.com/restatedev/sdk-java/pull/383)
  * Enable RawHandler test by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/385](https://github.com/restatedev/sdk-java/pull/385)
  * New test tool with new action by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/387](https://github.com/restatedev/sdk-java/pull/387)
  * Improve testing tools Javadocs by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/388](https://github.com/restatedev/sdk-java/pull/388)
  * Fix builds by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/389](https://github.com/restatedev/sdk-java/pull/389)
  * Introduce Spring Boot starter by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/393](https://github.com/restatedev/sdk-java/pull/393)
  * Spring boot improvements by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/394](https://github.com/restatedev/sdk-java/pull/394)
  * Add Json Schema for Req/Res types by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/395](https://github.com/restatedev/sdk-java/pull/395)
  * Add documentation and metadata fields to EndpointManifest by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/397](https://github.com/restatedev/sdk-java/pull/397)
  * Add title for classes by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/398](https://github.com/restatedev/sdk-java/pull/398)
  * Bump minimum JDK to 17 by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/400](https://github.com/restatedev/sdk-java/pull/400)
  * Bump minimum protocol version to 2 by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/401](https://github.com/restatedev/sdk-java/pull/401)
  * Fix case where we pass ServiceDefinition to the builder already by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/402](https://github.com/restatedev/sdk-java/pull/402)
  * Simple Json Schemas for Kotlin by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/403](https://github.com/restatedev/sdk-java/pull/403)
  * Allow checked exceptions in annotated services by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/407](https://github.com/restatedev/sdk-java/pull/407)
  * Fix code generation warning by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/408](https://github.com/restatedev/sdk-java/pull/408)
  * More dependency bumping by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/409](https://github.com/restatedev/sdk-java/pull/409)
  * Fix bad source version in ServiceProcessor by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/410](https://github.com/restatedev/sdk-java/pull/410)
  * Be lenient with ServiceLoader not able to load classes by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/411](https://github.com/restatedev/sdk-java/pull/411)
  * Few little improvements to testing by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/413](https://github.com/restatedev/sdk-java/pull/413)
  * \[Release] Bump to 1.2.0 by @github-actions in [https://github.com/restatedev/sdk-java/pull/412](https://github.com/restatedev/sdk-java/pull/412)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v1.2.0)
</Update>

<Update label="2024-10-16" description="Java/Kotlin SDK v1.1.1">
  ### What's Changed

  * Add interpreter test code by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/379](https://github.com/restatedev/sdk-java/pull/379)
  * Bump to 1.2.0-SNAPSHOT by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/380](https://github.com/restatedev/sdk-java/pull/380)
  * Make sure we don't check the invoke time for one way calls by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/381](https://github.com/restatedev/sdk-java/pull/381)
  * \[Release] Bump to 1.1.1 by @github-actions in [https://github.com/restatedev/sdk-java/pull/382](https://github.com/restatedev/sdk-java/pull/382)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v1.1.1)
</Update>

<Update label="2024-09-09" description="Java/Kotlin SDK v1.1.0">
  ### New features

  * \[Preview] Add retry policies for `run` operations, to limit the amount of retries/the duration of the retries
  * The ingress client now supports the ability to retrieve invocations/attach to existing invocations using idempotency id

  ### What's Changed

  * \[Release] Bump to 1.1.0-SNAPSHOT by @github-actions in [https://github.com/restatedev/sdk-java/pull/350](https://github.com/restatedev/sdk-java/pull/350)
  * Javadocs by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/347](https://github.com/restatedev/sdk-java/pull/347)
  * Add javadocs test by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/352](https://github.com/restatedev/sdk-java/pull/352)
  * buildAndListen now fails on port not available by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/353](https://github.com/restatedev/sdk-java/pull/353)
  * Add support to retrieve invocations from idempotency key by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/359](https://github.com/restatedev/sdk-java/pull/359)
  * Better error message when missing context parameter by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/360](https://github.com/restatedev/sdk-java/pull/360)
  * Fix Serde nullability annotations by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/361](https://github.com/restatedev/sdk-java/pull/361)
  * Sdk test tool by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/362](https://github.com/restatedev/sdk-java/pull/362)
  * Bump sdk-test-suite to 1.4 by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/363](https://github.com/restatedev/sdk-java/pull/363)
  * E2E actions for running in runtime by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/364](https://github.com/restatedev/sdk-java/pull/364)
  * More info on ingress logs by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/365](https://github.com/restatedev/sdk-java/pull/365)
  * Update sdk-test-suite to 1.5 by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/366](https://github.com/restatedev/sdk-java/pull/366)
  * Fix usage of new ingress exception constructor by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/367](https://github.com/restatedev/sdk-java/pull/367)
  * Add env vars by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/368](https://github.com/restatedev/sdk-java/pull/368)
  * A couple of changes to allow override the test artifact output (which would otherwise conflict) by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/369](https://github.com/restatedev/sdk-java/pull/369)
  * Remove the old e2e job by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/370](https://github.com/restatedev/sdk-java/pull/370)
  * New upgrade test by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/371](https://github.com/restatedev/sdk-java/pull/371)
  * Update test tool to 1.8, with new delayed calls test by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/372](https://github.com/restatedev/sdk-java/pull/372)
  * Make sure private methods cannot be annotated by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/377](https://github.com/restatedev/sdk-java/pull/377)
  * Don't try to handle `Error` by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/376](https://github.com/restatedev/sdk-java/pull/376)
  * Implement run retry policy by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/375](https://github.com/restatedev/sdk-java/pull/375)
  * \[Release] Bump to 1.1.0 by @github-actions in [https://github.com/restatedev/sdk-java/pull/378](https://github.com/restatedev/sdk-java/pull/378)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v1.1.0)
</Update>

<Update label="2024-06-07" description="Java/Kotlin SDK v1.0.0">
  We're happy to announce that Restate has reached the 1.0 milestone!

  Check the [Restate 1.0](https://github.com/restatedev/restate/releases/tag/v1.0.0) release for more details.

  ### Workflow API

  We have introduced a new API to simplify building workflows, check out the documentation: [https://docs.restate.dev/develop/java/workflows](https://docs.restate.dev/develop/java/workflows)

  ### Breaking changes from 0.9

  * Split CoreSerdes in JsonSerdes for the json primitive types and move RAW, BYTE\_BUFFER AND VOID into the `Serde` interface by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/330](https://github.com/restatedev/sdk-java/pull/330)
  * Remove protobuf from the public api of sdk-common by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/321](https://github.com/restatedev/sdk-java/pull/321)
  * Rename the ingress client and the connect method by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/336](https://github.com/restatedev/sdk-java/pull/336)

  ### Other changes

  * \[Release] Bump to 0.10.0-SNAPSHOT by @github-actions in [https://github.com/restatedev/sdk-java/pull/308](https://github.com/restatedev/sdk-java/pull/308)
  * Update admin api by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/313](https://github.com/restatedev/sdk-java/pull/313)
  * Update Openapi generator to newest version by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/314](https://github.com/restatedev/sdk-java/pull/314)
  * Integrate Java SDK with new service protocol negotiation mechanism by @tillrohrmann in [https://github.com/restatedev/sdk-java/pull/318](https://github.com/restatedev/sdk-java/pull/318)
  * Fix double logging the end message by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/319](https://github.com/restatedev/sdk-java/pull/319)
  * Remove protobuf from the public api of sdk-common by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/321](https://github.com/restatedev/sdk-java/pull/321)
  * Fix submit disambiguation by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/320](https://github.com/restatedev/sdk-java/pull/320)
  * Verify that there can't be two handlers with same name by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/326](https://github.com/restatedev/sdk-java/pull/326)
  * Add WorkflowHandle by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/329](https://github.com/restatedev/sdk-java/pull/329)
  * Fix nullability problem wrt return type of kotlin services by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/331](https://github.com/restatedev/sdk-java/pull/331)
  * Add SendStatus by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/332](https://github.com/restatedev/sdk-java/pull/332)
  * Java/Kotlin docs for the new workflow api by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/333](https://github.com/restatedev/sdk-java/pull/333)
  * Now send acks on combinators by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/334](https://github.com/restatedev/sdk-java/pull/334)
  * Consecutive GetState with empty by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/335](https://github.com/restatedev/sdk-java/pull/335)
  * Max concurrent streams by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/337](https://github.com/restatedev/sdk-java/pull/337)
  * Rename the ingress client and the connect method by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/336](https://github.com/restatedev/sdk-java/pull/336)
  * \[kotlin] Fix nested types input/output code generation by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/273](https://github.com/restatedev/sdk-java/pull/273)
  * General dependency bump by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/339](https://github.com/restatedev/sdk-java/pull/339)
  * Allow more than one key in request signing by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/340](https://github.com/restatedev/sdk-java/pull/340)
  * Add Awaitable#all(List) and Awaitable#any(List) by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/338](https://github.com/restatedev/sdk-java/pull/338)
  * A lot of small linter fixes by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/341](https://github.com/restatedev/sdk-java/pull/341)
  * Fix getOutput return type by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/342](https://github.com/restatedev/sdk-java/pull/342)
  * Fix GetOutput status code error handling -\_-" by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/343](https://github.com/restatedev/sdk-java/pull/343)
  * Move all the encoding/decoding of messages within sdk-core by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/344](https://github.com/restatedev/sdk-java/pull/344)
  * Remove stream when initializing user state storage by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/345](https://github.com/restatedev/sdk-java/pull/345)
  * minor doc fix by @AhmedSoliman in [https://github.com/restatedev/sdk-java/pull/346](https://github.com/restatedev/sdk-java/pull/346)
  * Adjust the README for 1.0 by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/348](https://github.com/restatedev/sdk-java/pull/348)
  * \[Release] Bump to 1.0.0 by @github-actions in [https://github.com/restatedev/sdk-java/pull/349](https://github.com/restatedev/sdk-java/pull/349)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v1.0.0)
</Update>

<Update label="2024-05-03" description="Java/Kotlin SDK v0.9.2">
  ### What's Changed

  * \[Release] Bump to 0.10.0-SNAPSHOT by @github-actions in [https://github.com/restatedev/sdk-java/pull/306](https://github.com/restatedev/sdk-java/pull/306)
  * Raw handlers by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/303](https://github.com/restatedev/sdk-java/pull/303)
  * \[Release] Bump to 0.9.2 by @github-actions in [https://github.com/restatedev/sdk-java/pull/307](https://github.com/restatedev/sdk-java/pull/307)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v0.9.2)
</Update>

<Update label="2024-04-30" description="Java/Kotlin SDK v0.9.1">
  ### What's Changed

  * \[Release] Bump to 0.10.0-SNAPSHOT by @github-actions in [https://github.com/restatedev/sdk-java/pull/301](https://github.com/restatedev/sdk-java/pull/301)
  * Update README by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/271](https://github.com/restatedev/sdk-java/pull/271)
  * Update workflow deps by @tillrohrmann in [https://github.com/restatedev/sdk-java/pull/302](https://github.com/restatedev/sdk-java/pull/302)
  * Implement request identity by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/297](https://github.com/restatedev/sdk-java/pull/297)
  * VOID should return null content type by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/304](https://github.com/restatedev/sdk-java/pull/304)
  * \[Release] Bump to 0.9.1 by @github-actions in [https://github.com/restatedev/sdk-java/pull/305](https://github.com/restatedev/sdk-java/pull/305)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v0.9.1)
</Update>

<Update label="2024-04-25" description="Java/Kotlin SDK v0.9.0">
  This release features a completely overhauled development experience. We suggest checking out the new documentation [https://docs.restate.dev/develop/java/overview](https://docs.restate.dev/develop/java/overview) for more details and the new examples [https://github.com/restatedev/examples](https://github.com/restatedev/examples).

  ### What's Changed

  * \[Release] Bump to 0.9.0-SNAPSHOT by @github-actions in [https://github.com/restatedev/sdk-java/pull/233](https://github.com/restatedev/sdk-java/pull/233)
  * New interface refactor by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/236](https://github.com/restatedev/sdk-java/pull/236)
  * New interface refactor (sdk-api-kotlin) by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/238](https://github.com/restatedev/sdk-java/pull/238)
  * sdk-api-kotlin-gen by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/240](https://github.com/restatedev/sdk-java/pull/240)
  * Use simple class name as default name by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/241](https://github.com/restatedev/sdk-java/pull/241)
  * Request headers and Executor injection changes. by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/242](https://github.com/restatedev/sdk-java/pull/242)
  * Remove TerminalException.Code enum and replace it with just an integer. by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/248](https://github.com/restatedev/sdk-java/pull/248)
  * Add RequestOptions to ingress requests by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/250](https://github.com/restatedev/sdk-java/pull/250)
  * Move Protobuf serde to separate module by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/253](https://github.com/restatedev/sdk-java/pull/253)
  * Make the ingress client async by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/252](https://github.com/restatedev/sdk-java/pull/252)
  * Add resolve/reject awakeables from ingress by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/254](https://github.com/restatedev/sdk-java/pull/254)
  * Fix bad request error code by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/255](https://github.com/restatedev/sdk-java/pull/255)
  * Fix ingress awakeable resolve/reject by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/256](https://github.com/restatedev/sdk-java/pull/256)
  * Fix broken links to the docs by @gvdongen in [https://github.com/restatedev/sdk-java/pull/257](https://github.com/restatedev/sdk-java/pull/257)
  * Adapt latest protocol changes by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/258](https://github.com/restatedev/sdk-java/pull/258)
  * Correct content-type by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/261](https://github.com/restatedev/sdk-java/pull/261)
  * Merge send methods and rename with in bind by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/263](https://github.com/restatedev/sdk-java/pull/263)
  * Fix usage of IngressClient in code generated by kotlin gen by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/264](https://github.com/restatedev/sdk-java/pull/264)
  * Fix logging context propagation by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/270](https://github.com/restatedev/sdk-java/pull/270)
  * Rename ctx.sideEffect in ctx.run by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/267](https://github.com/restatedev/sdk-java/pull/267)
  * Fix options injection in kt codegen by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/274](https://github.com/restatedev/sdk-java/pull/274)
  * Remove idempotency retain period from ingress client options by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/268](https://github.com/restatedev/sdk-java/pull/268)
  * Add support for Send delay in ingress client by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/275](https://github.com/restatedev/sdk-java/pull/275)
  * More implicitness in kotlin by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/277](https://github.com/restatedev/sdk-java/pull/277)
  * More logging on jackson ser/de by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/279](https://github.com/restatedev/sdk-java/pull/279)
  * Fix corner cases around code generation and "reserved" keywords by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/280](https://github.com/restatedev/sdk-java/pull/280)
  * Named side effects by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/282](https://github.com/restatedev/sdk-java/pull/282)
  * Side effects changes by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/284](https://github.com/restatedev/sdk-java/pull/284)
  * Add x-restate-server header in responses by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/285](https://github.com/restatedev/sdk-java/pull/285)
  * Renaming components -> services by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/287](https://github.com/restatedev/sdk-java/pull/287)
  * Implement Shared handlers annotation for virtual objects by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/288](https://github.com/restatedev/sdk-java/pull/288)
  * Renamings 2 by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/289](https://github.com/restatedev/sdk-java/pull/289)
  * Add "Start invocation" in InvocationStateMachine, symmetric with "End invocation" log line by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/290](https://github.com/restatedev/sdk-java/pull/290)
  * Add checkEntryHeader to output entry by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/291](https://github.com/restatedev/sdk-java/pull/291)
  * Propagate `otelContext` in `Request` and in thread-local/coroutine context by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/296](https://github.com/restatedev/sdk-java/pull/296)
  * Remove Serde#schema by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/298](https://github.com/restatedev/sdk-java/pull/298)
  * Add metadata by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/299](https://github.com/restatedev/sdk-java/pull/299)
  * \[Release] Bump to 0.9.0 by @github-actions in [https://github.com/restatedev/sdk-java/pull/300](https://github.com/restatedev/sdk-java/pull/300)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v0.9.0)
</Update>

<Update label="2024-03-01" description="Java/Kotlin SDK v0.8.0">
  ### What's Changed

  * \[Release] Bump to 0.7.1-SNAPSHOT by @github-actions in [https://github.com/restatedev/sdk-java/pull/203](https://github.com/restatedev/sdk-java/pull/203)
  * Upgrade gradle and add .ignore by @AhmedSoliman in [https://github.com/restatedev/sdk-java/pull/205](https://github.com/restatedev/sdk-java/pull/205)
  * Awakeable IDs following the new ID scheme by @AhmedSoliman in [https://github.com/restatedev/sdk-java/pull/204](https://github.com/restatedev/sdk-java/pull/204)
  * Isolate gRPC code by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/195](https://github.com/restatedev/sdk-java/pull/195)
  * Support Kotlin target in the protoc plugin by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/196](https://github.com/restatedev/sdk-java/pull/196)
  * Bumped testcontainers and vertx by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/209](https://github.com/restatedev/sdk-java/pull/209)
  * Serialize state as JSON. by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/208](https://github.com/restatedev/sdk-java/pull/208)
  * `Awaitable#map` by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/210](https://github.com/restatedev/sdk-java/pull/210)
  * Split RestateContext interface in KeyedContext/UnkeyedContext by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/213](https://github.com/restatedev/sdk-java/pull/213)
  * Workflow API by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/215](https://github.com/restatedev/sdk-java/pull/215)
  * Stop assuming input and output of invocations implement MessageLite by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/214](https://github.com/restatedev/sdk-java/pull/214)
  * `KeyedContext#clearAll` by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/217](https://github.com/restatedev/sdk-java/pull/217)
  * Add `ctx.stateKeys()` by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/219](https://github.com/restatedev/sdk-java/pull/219)
  * A bunch of fixes for the Workflow API by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/222](https://github.com/restatedev/sdk-java/pull/222)
  * Add API to sdk-testing to mount workflows. by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/223](https://github.com/restatedev/sdk-java/pull/223)
  * Rename `UnkeyedContext` to `Context` by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/220](https://github.com/restatedev/sdk-java/pull/220)
  * Fix suffix problem with workflow api. by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/225](https://github.com/restatedev/sdk-java/pull/225)
  * Add support for kotlin serialization by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/224](https://github.com/restatedev/sdk-java/pull/224)
  * Bump protocol version by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/226](https://github.com/restatedev/sdk-java/pull/226)
  * Handler API by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/227](https://github.com/restatedev/sdk-java/pull/227)
  * \[Release] Bump to 0.8.0 by @github-actions in [https://github.com/restatedev/sdk-java/pull/232](https://github.com/restatedev/sdk-java/pull/232)

  ### New Contributors

  * @AhmedSoliman made their first contribution in [https://github.com/restatedev/sdk-java/pull/205](https://github.com/restatedev/sdk-java/pull/205)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v0.8.0)
</Update>

<Update label="2024-02-01" description="Java/Kotlin SDK v0.7.0">
  ### What's Changed

  * \[Release] Bump to 0.7.0-SNAPSHOT by @github-actions in [https://github.com/restatedev/sdk-java/pull/182](https://github.com/restatedev/sdk-java/pull/182)
  * Update meta API by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/186](https://github.com/restatedev/sdk-java/pull/186)
  * Fix logging context propagation by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/185](https://github.com/restatedev/sdk-java/pull/185)
  * Update SDK to use restatedev/service-protocol#58  by @tillrohrmann in [https://github.com/restatedev/sdk-java/pull/189](https://github.com/restatedev/sdk-java/pull/189)
  * Log improvements by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/194](https://github.com/restatedev/sdk-java/pull/194)
  * Introduce deterministic random by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/178](https://github.com/restatedev/sdk-java/pull/178)
  * Use target/source compatibility rather than selecting a specific toolchain by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/197](https://github.com/restatedev/sdk-java/pull/197)
  * Check protocol version is supported by @slinkydeveloper in [https://github.com/restatedev/sdk-java/pull/199](https://github.com/restatedev/sdk-java/pull/199)
  * \[Release] Bump to 0.7.0 by @github-actions in [https://github.com/restatedev/sdk-java/pull/200](https://github.com/restatedev/sdk-java/pull/200)

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v0.7.0)
</Update>

<Update label="2023-12-13" description="Java/Kotlin SDK v0.6.0">
  See [https://docs.restate.dev/quickstart/](https://docs.restate.dev/quickstart/) for more details

  [View on GitHub](https://github.com/restatedev/sdk-java/releases/tag/v0.6.0)
</Update>
