Releases: restatedev/sdk-java
Release list
v2.9.0
Restate Java/Kotlin SDK 2.9.0
New API is now the default; codegen API deprecated
The codegen API based on the sdk-api-gen annotation processor / sdk-api-kotlin-gen KSP generator is now deprecated and will be removed in a future release.
Prefer the new API: no annotation processor, handlers drop the Context parameter for the static dev.restate.sdk.Restate methods (Java) or the top-level functions in dev.restate.sdk.kotlin (Kotlin).
Annotations remain the same (@Service, @Handler, …), so migrating is mostly removing the Context parameter and changing how you invoke other services.
The two styles coexist, so you can migrate one service at a time.
// Before (codegen API)
@Handler
public void add(ObjectContext ctx, long value) {
long current = ctx.get(TOTAL).orElse(0L);
ctx.set(TOTAL, current + value);
}
// After (new API)
@Handler
public void add(long value) {
var state = Restate.state();
long current = state.get(TOTAL).orElse(0L);
state.set(TOTAL, current + value);
}See the Migration guide for the full Context API → new API mapping and step-by-step instructions for both Java and Kotlin.
Native core (JDK 23+)
On JDK >= 23 the SDK now runs its core logic, referred as "protocol state machine", through the native shared-core library via Panama/FFM, providing all the latest Restate features to the Java SDK.
- If you run on JDK >= 23, no action is required to use the new core.
- If you run on JDK < 23, the SDK falls back to a pure-Java state machine, which is deprecated. In that case, we suggest upgrading to JDK >= 25.
Check https://github.com/restatedev/sdk-java/tree/main#native-access-on-jdk-23 for more details.
(Preview) Scope and limit key to enable flow control
This release adds the SDK API for flow control, the new Restate 1.7 feature to cap how many invocations run concurrently within a scope, with optional hierarchical limit keys.
Use it to bound cost (especially for AI agents, where every concurrent invocation is real model/API spend), shield downstream systems from bursts, and share capacity fairly across tenants.
To use scope and limit keys in service to service communication:
// Route a call into a named scope
Restate.scope("tenant-123").service(MyService.class).process(payload);
// Add a limit key for hierarchical concurrency limits within the scope
Restate.scope("tenant-123").workflowHandle(MyWorkflow.class, "wf-key")
.call(MyWorkflow::run, input, InvocationOptions.limitKey("api-key/user42").build())
.await();The same API is available on the ingress Client (client.scope("tenant-123").service(MyService.class)).
Check out the Flow control documentation for more details on how concurrency limits work and how to set them up.
NOTE: This API is in preview and is not enabled by default. To use it in restate-server 1.7, enable the flow control and protocol v7 experimental features via
RESTATE_EXPERIMENTAL_ENABLE_PROTOCOL_V7=trueandRESTATE_EXPERIMENTAL_ENABLE_VQUEUES=true(new clusters only). See https://docs.restate.dev/services/flow-control for details.
Signals API
Signals let invocations communicate directly with each other: one invocation waits for a signal, and any other handler can resolve or reject it by referencing the target invocation's ID.
// Inside the invocation that wants to wait:
boolean approved = Restate.signal("approved", Boolean.class).await();
// Inside another handler that knows the target invocation's ID:
InvocationHandle<?> target = Restate.invocationHandle(targetInvocationId);
target.signal("approved").resolve(Boolean.class, true);
// or, to wake the waiter with a terminal error:
target.signal("approved").reject("Request denied");Restate.invocationHandle(invocationId) returns an InvocationHandle, which you can also use to cancel() the target invocation or attach() to wait for its result.
Other changes
- Configurable, multi-event-loop HTTP server, enabled by default. The Vert.x HTTP server now runs on multiple event loops out of the box. Configure it in Spring via
restate.sdk.http.eventLoops, or in the vanilla SDK via theRESTATE_SDK_HTTP_EVENT_LOOPSenv variable /dev.restate.sdk.http.eventLoopssystem property. - Generic calls/sends. Added
Restate.call(request)/Restate.send(request[, delay])in Java andprepareRequest(request).call()/prepareRequest(request).send(delay)in Kotlin, for invoking services from a rawRequest. - Admin client deprecated. The admin client is now deprecated.
- Vert.x 5 compatibility. Fixed a compatibility issue with Vert.x 5.
- JSON schema
$refbugfix.DefaultJsonSchemaFactoryno longer replaces a nested type name when it merely shares the prefix of the root class name (e.g.Task&TaskType), which previously produced an unserializable schema that crashed at runtime. - Dependency bumps. Minimum Jackson version bumped (along with AssertJ and Kotlin); Kotlin and KSP bumped to 2.3.0.
New Contributors
Full Changelog: v2.8.0...v2.9.0
v2.8.0
Out-of-the-box tracing support
Using Spring Boot
The Spring Boot starters wire up automatically all you need for tracing, given an ObservationRegistry bean is present.
All you need is the standard Spring Boot tracing setup. Add the following dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Required for the Restate Client instrumentation, not shipped by spring-boot-actuator -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-java11</artifactId>
</dependency>And configure the exporter of your choice.
For more details on setting up supported exporters, refer to the Spring Boot tracing documentation.
To set up a sample OTLP tracing exporter, add the following dependencies:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>And setup the tracing endpoint in the application.properties:
# Sample every request (tune for production)
management.tracing.sampling.probability=1.0
# OTLP gRPC endpoint (e.g. Jaeger on 4317). Use 4318 + transport=http_protobuf for HTTP/protobuf.
management.otlp.tracing.endpoint=http://localhost:4317
management.otlp.tracing.transport=grpcUsing OpenTelemetry with vanilla SDK
The new module dev.restate:sdk-interceptor-opentelemetry adds tracing for both the Java and Kotlin APIs:
- For every handler invocation attempt, an
attempt <target>span is created, and linked up automatically with the parent span propagated from Restate. - For every executed
ctx.run(name, ...)block, arun (<name>)child span is created. Spans are automatically propagated to the thread executing therunclosure.
To configure:
- Set up a
GlobalOpenTelemetryusing the OpenTelemetry SDK. The easiest way is to use OpenTelemetry autoconfigure SDK as shown in this official example - Manually set up a specific
OpenTelemetryinstance and register the factory:
var otel = new OpenTelemetryInterceptorFactory(openTelemetry);
var endpoint =
Endpoint.bind(
new MyService(),
new HandlerRunner.Options()
.addHandlerInterceptorFactory(otel)
.addRunInterceptorFactory(otel))
.build();Using Micrometer with vanilla SDK
The new module dev.restate:sdk-interceptor-micrometer adds tracing through Micrometer Observation for both the Java and Kotlin APIs:
- For every handler invocation attempt, an
attempt <target>observation is created, and linked up automatically with the parent span propagated from Restate. - For every executed
ctx.run(name, ...)block, arun (<name>)child observation is created. Observations are automatically propagated to the thread executing therunclosure.
Spans produced through the Micrometer tracing bridge mirror those emitted by the OpenTelemetry integration, so dashboards look the same regardless of which integration you pick.
To configure, set up an ObservationRegistry instance and register the factory:
var micrometer = new MicrometerInterceptorFactory(observationRegistry);
var endpoint =
Endpoint.bind(
new MyService(),
new HandlerRunner.Options()
.addHandlerInterceptorFactory(micrometer)
.addRunInterceptorFactory(micrometer))
.build();New interceptor API
The new tracing support is built on a new public interceptor API in dev.restate.sdk.interceptor (Java) and dev.restate.sdk.kotlin.interceptor (Kotlin), which you can use to plug in your own cross-cutting concerns, such as custom tracing, metrics, MDC/logging scopes, error mapping, and so on.
Check out the Javadocs or Kotlindocs for more details.
The interceptor API is marked experimental and may change in future releases.
Full Changelog: v2.7.0...v2.8.0
v2.7.0
What's Changed
TerminalException metadata
You can now attach metadata to a TerminalException:
throw new TerminalException("Something went wrong", Map.of("correlationId", "abc123"));The metadata map is propagated to callers and is accessible via TerminalException.getMetadata(). Requires restate-server >= 1.6.
Spring Boot: global default service configuration
Top-level restate.* properties now act as defaults applied to all registered services. Per-service restate.components.<Name>.* properties override them on a per-service basis:
# Applied to all services by default
restate.journal-retention=PT48H
restate.inactivity-timeout=PT10M
restate.retry-policy.max-attempts=5
# Overrides just for MyService
restate.components.MyService.journal-retention=PT72H
restate.components.MyService.ingress-private=trueSupported global defaults: documentation, metadata, inactivity-timeout, abort-timeout, idempotency-retention, workflow-retention, journal-retention, ingress-private, enable-lazy-state, retry-policy.
ctx.random() now returns a stable instance
ctx.random() previously created a new RestateRandom instance on every call. It now returns the same instance for the lifetime of the invocation.
Note: This is a behavior change affecting
ctx.random()output ordering when called multiple times in the same handler. If you usectx.random(), redeploy your service as a new version to avoid replay mismatches. See the Restate versioning policy for guidance.
Changelog
- Add TerminalException.metadata field by @slinkydeveloper in #596
- Test TerminalError.metadata by @slinkydeveloper in #598
- Use WarpBuild runners for CI workflows by @tillrohrmann in #600
- Add check for context run by @slinkydeveloper in #601
- Port await mismatch by @slinkydeveloper in #602
- [spring] Add global default service configuration by @slinkydeveloper in #605
- Create the Random instance only once by @slinkydeveloper in #606
Full Changelog: v2.6.0...v2.7.0
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.<name>.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
# 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=30dAnnotation based configuration
The configuration attribute on @RestateService, @RestateVirtualObject, and @RestateWorkflow annotations now accepts a bean name of type RestateComponentProperties (previously RestateServiceConfigurator):
@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
Contextparameter. Instead, use top-level functions fromdev.restate.sdk.kotlinto 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
-
Remove the KSP code generator dependency
sdk-api-kotlin-gen -
Remove the
Context,ObjectContext,SharedObjectContext,WorkflowContext,SharedWorkflowContextparameters from your@Handlerannotated methods. For example:@VirtualObject class Counter { @Handler suspend fun add(ctx: ObjectContext, value: Long) {} @Shared @Handler suspend fun get(ctx: SharedObjectContext): Long {} }
Becomes:
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.
-
Replace all the usages of
ctx.with the top-level functions. For example:@Handler suspend fun add(ctx: ObjectContext, value: Long) { val currentValue = ctx.get(TOTAL) ?: 0L val newValue = currentValue + value ctx.set(TOTAL, newValue) }
Becomes:
@Handler suspend fun add(value: Long) { val state = state() val currentValue = state.get(TOTAL) ?: 0L val newValue = currentValue + value state.set(TOTAL, newValue) }
-
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<T>(),virtualObject<T>(key)andworkflow<T>(key):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<T>(),toVirtualObject<T>(key)andtoWorkflow<T>(key):// 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 { ... }/ctx.runAsync { ... } |
runBlock { ... }/runAsync { ... } |
ctx.random() |
random() |
ctx.timer() |
timer() |
ctx.awakeable() |
awakeable<T>() |
ctx.get(key) / ctx.set(key, value) |
state().get(key) / state().set(key, value) |
ctx.promise(key) |
promise(key) |
| Code generated clients (Services) | service<T>() / toService<T>() |
| Code generated clients (Virtual Objects) | virtualObject<T>(key) / toVirtualObject<T>(key) |
| Code generated clients (Workflows) | workflow<T>(key) / toWorkflow<T>(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<MyServiceInterface>(). - Use
openin all Restate annotated classes/methods. - Setup the Kotlin allopen compiler plugin with the following configuration:
Gradle (Kotlin DSL)
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)
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
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
import kotlin.time.Clock
import kotlin.time.ExperimentalTime
import dev.restate.sdk.kotlin.*
@...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
Contextparameter. Instead, use static methods from theRestateclass 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
-
Remove the annotation processor dependency
sdk-api-gen -
Remove the
Context,ObjectContext,SharedObjectContext,WorkflowContext,SharedWorkflowContextparameters from your@Handlerannotated methods. For example:@VirtualObject public class Counter { @Handler public void add(ObjectContext ctx, long request) {} @Shared @Handler public long get(SharedObjectContext ctx) {} }
Becomes:
@VirtualObject public class Counter { @Handler public void add(long request) {} @Shared @Handler public long get() {} }
The same applies for interfaces using Restate annotations.
-
Replace all the usages of
ctx.withRestate.. For example:@Handler public void add(ObjectContext ctx, long value) { long currentValue = ctx.get(TOTAL).orElse(0L); long newValue = currentValue + value; ctx.set(TOTAL, newValue); }
Becomes:
@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); }
-
Replace all the usages of code-generated clients. There are two ways to invoke services:
Simple proxy (for direct calls):
The
Restateclass lets you create proxies to call services directly usingservice(Class),virtualObject(Class, key)andworkflow(Class, key):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)andworkflowHandle(Class, key):// 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
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
<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>Full Changelog: v2.4.2...v2.5.0
v2.4.2
What's Changed
- Various improvements to the code generator
New Contributors
- @muhamadazmy made their first contribution in #562
- @squarepegg made their first contribution in #563
Full Changelog: v2.4.1...v2.4.2
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. #556
- bump handlebars dependency from 4.3.1 to 4.5.0 by @djarnis73 in #557
New Contributors
- @djarnis73 made their first contribution in #557
Full Changelog: v2.4.0...v2.4.1
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 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:
// 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 #531
- Bump org.assertj:assertj-core from 3.26.0 to 3.27.4 by @dependabot[bot] in #536
- Retry policy by @slinkydeveloper in #540
- Protocol V6 + random_seed support by @slinkydeveloper in #542
- Test Suite v3.1 by @slinkydeveloper in #545
- Clarify max attempts meaning by @slinkydeveloper in #546
- Add workflow retention setting at service level by @slinkydeveloper in #547
- Add entrypoint to setup a configurator for Spring Restate services. by @slinkydeveloper in #548
- Dependency bumps by @slinkydeveloper in #549
- [Release] Bump to 2.4.0 by @github-actions[bot] in #550
Full Changelog: v2.3.0...v2.4.0
v2.3.0
IMPORTANT For Spring Users: Due to MadeYourReset CVE, 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.Finalto thegradle.propertiesfile
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:
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
delayto generated workflow clientssubmitmethod - 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
Full Changelog: v2.2.1...v2.3.0
v2.2.1
What's Changed
- [Release] Bump to 2.3.0-SNAPSHOT by @github-actions[bot] in #512
- Few improvements to errors from sdk-shared-core by @slinkydeveloper in #513
- Improve formatting of journal mismatch by @slinkydeveloper in #514
- Fix usage of filer/classloader for resources. by @slinkydeveloper in #517
- Add commandIndex to mismatch exceptions by @slinkydeveloper in #518
- [Release] Bump to 2.2.1 by @github-actions[bot] in #519
Full Changelog: v2.2.0...v2.2.1