Repository navigation
Java jackson 3 version upgrade #569
Description
Activity
- changed the title
[-]Java jacson version upgrade[/-][+]Java jackson 3 version upgrade[/+]on Dec 30, 2025 This is high on my list!
- addeddependenciesPull requests that update a dependency filePull requests that update a dependency file
on Jan 5, 2026 I had to jump through some hoops recently with the sdk due to the dependency on Jackson 2. Is the intent of the maintainers to move to Jackson 3 or is Jackson 2 dependence planned to be continued for some time?
If so, I may begin the following proposal to reduce friction for Jackson 3-only projects:
Streamline Jackson 3 usage with existing Restate Java SDK
Feature Request / Bug: Modern Jackson 3 Support, Default JSR-310 (Java 8 Time), and Global Programmatic
SerdeFactoryConfigurationSummary
When building modern Java applications (e.g., Spring Boot 4+, Java 21/26) that use Jackson 3 (
tools.jackson.databind.*) and standard Java 8 Date/Time types (java.time.Instant,java.time.LocalDate), integrating with Restate Java SDK (v2.9.x) requires substantial workarounds.Specifically:
- Default
ObjectMapperlacks JSR-310 support: Out of the box,JacksonSerdeFactory.DEFAULTfails when serializingjava.time.InstantandLocalDate. - Hard-coupling to Jackson 2 (
com.fasterxml.jackson.*): Restate'sJacksonSerdeFactorycannot be subclassed or customized with a Jackson 3ObjectMapperdue to package/type mismatches. - No programmatic global
SerdeFactoryconfiguration onEndpoint.builder(): Services must each be individually annotated with@CustomSerdeFactory(Class), andServiceLoaderSPI (DefaultSerdeFactoryProvider) collisions occur ifsdk-serde-jacksonis on the classpath.
1. Problem Details
A. Default Jackson Serde Fails on
java.time.InstantandLocalDateWhen sending or receiving payloads containing standard
java.timetypes through handler parameters, awakeables, or durable state, Restate throws:com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.Instant` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (or disable `MapperFeature.REQUIRE_HANDLERS_FOR_JAVA8_TIMES`)Why this hurts: Modern Java applications almost exclusively use
java.time.Instantandjava.time.LocalDaterather thanjava.util.Date. Having the default serde fail on basic Java time types requires every developer to implement a custom serde factory just to pass a timestamp.B. Incompatibility with Jackson 3 (
tools.jackson.databind.*)In Jackson 3, package names moved from
com.fasterxml.jackson.databind.*totools.jackson.databind.*, and Java 8 date/time is supported natively without external modules.However, the Restate Java SDK documentation recommends:
class MyJacksonSerdeFactory extends JacksonSerdeFactory { public MyJacksonSerdeFactory() { super(new ObjectMapper().configure(...)); } }
Because
JacksonSerdeFactorystrictly acceptscom.fasterxml.jackson.databind.ObjectMapper, projects enforcing Jackson 3 cannot reuseJacksonSerdeFactoryorJacksonSerdes. Developers must manually implement the low-leveldev.restate.serde.SerdeFactoryinterface from scratch usingSerde.using(...)andtools.jackson.databind.JavaType.C. Inability to Programmatically Set a Global
SerdeFactoryonEndpointCurrently, when registering services on an
Endpoint:Endpoint.builder() .bind(service1) .bind(service2) .build();
There is no method such as
Endpoint.builder().withSerdeFactory(mySerdeFactory).Instead, developers must:
- Annotate every single
@Service,@VirtualObject, and@Workflowclass with@CustomSerdeFactory(MyFactory.class). - Or rely on the
ServiceLoaderSPI (DefaultSerdeFactoryProvider). However,dev.restate:sdk-serde-jacksonalready bundles aDefaultSerdeFactoryProviderinMETA-INF/services/. If an application registers its ownDefaultSerdeFactoryProvider,ServiceLoader.load(DefaultSerdeFactoryProvider.class)discovers 2 providers. When multiple providers are discovered, Restate'sClientImpldisables default serde resolution with a warning:"When creating the Client, more than one SerdeFactory was found. To prevent unexpected behavior, the client was configured without SerdeFactory."
2. Proposed Improvements
1. Register
JavaTimeModuleby Default inJacksonSerdeFactoryIn
dev.restate:sdk-serde-jackson, defaultObjectMapperinstances should registerJavaTimeModule(or invokefindAndRegisterModules()):public static ObjectMapper defaultObjectMapper() { return new ObjectMapper() .registerModule(new JavaTimeModule()) .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); }
This single change would eliminate
InvalidDefinitionExceptionfor all Jackson 2 users out of the box.2. Introduce a
dev.restate:sdk-serde-jackson3Module (or decouple SerdeFactory from Jackson 2)Provide first-class Jackson 3 support by publishing a dedicated
sdk-serde-jackson3artifact usingtools.jackson.databind.*, or provide an interface abstraction for JSON object mappers so that applications can supply either Jackson 2 or Jackson 3 without custom boilerplate.3. Add
Endpoint.Builder#withDefaultSerdeFactory(SerdeFactory)Allow developers to configure a default
SerdeFactoryprogrammatically when building theEndpoint:Endpoint.builder() .withDefaultSerdeFactory(new MyCustomSerdeFactory()) .bind(service1) .bind(service2) .build();
If present, this factory would serve as the fallback for any service that does not declare an explicit
@CustomSerdeFactoryannotation, avoiding SPI collisions and repetitive annotations across dozens of services.4. Symmetric Builder API for
ClientandEndpointBoth
Endpoint.builder()andClient.builder()(orClient.connect(baseUri, serdeFactory)) should share a consistent mechanism for setting the defaultSerdeFactory, so that client-side and server-side serde behavior remain identical across durable awakeables and RPC calls.
Environment
- Restate Java SDK: 2.9.3
- JDK: 21+ / 26
- Build Tool: Gradle 9+ Kotlin DSL
- Jackson:
tools.jackson.core:jackson-databind:3.1.4(Jackson 3 BOM 3.2.1)
Reacted by Marko Radinovic- Default
New version of jacson 3.x is released. but latest restate springbboot SDK is using jacson 2.x.
https://mvnrepository.com/artifact/tools.jackson.core/jackson-core