How to handle Java 8 date/time serialization with Dapr's Java SDK

65 Views Asked by At

I'm currently developing a Spring Boot application using Dapr's Java SDK version 1.9.0. I'm encountering a serialization issue when I try to publish an event that contains a java.time.Instant object.

I am having these dependencies relevant to DAPR :

  implementation 'io.dapr:dapr-sdk:1.9.0'
  implementation 'io.dapr:dapr-sdk-springboot:1.9.0'
  implementation 'io.dapr:dapr-sdk-actors:1.9.0'
  implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.0'
  implementation 'com.squareup.okhttp3:okhttp:4.9.3'

The stack trace points to Dapr's internal ObjectSerializer:

io.dapr.exceptions.DaprException: UNKNOWN: Java 8 date/time type `java.time.Instant` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: ...)] 

I have already added the jackson-datatype-jsr310 dependency to my project and registered the module with my application's ObjectMapper. However, it seems like Dapr's ObjectSerializer is using a different ObjectMapper instance.

Here's the relevant part of my code:

// ... other code ...  
Job job = new Job();  
job.setQueued(Instant.now());  
daprClient.publishEvent("myTopic", job).block();  
// ... other code ..

.

Is there a way to customize the ObjectMapper used by Dapr's ObjectSerializer? Or is there another workaround to use java.time.Instant with Dapr's Java SDK? Any help would be appreciated!

1

There are 1 best solutions below

0
On

Resolved this issue by creating a custom serializer class and included javaTimeModule() to ObjectMapper instance.

public class JacksonDaprObjectSerializer implements DaprObjectSerializer {

    private final ObjectMapper objectMapper;

    public JacksonDaprObjectSerializer(ObjectMapper objectMapper) {
        objectMapper.registerModule(new JavaTimeModule());
        this.objectMapper = objectMapper;
    }

    @Override
    public byte[] serialize(Object o) {
        try {
            return objectMapper.writeValueAsBytes(o);
        } catch (IOException e) {
            throw new DaprException(e);
        }
    }

    @Override
    public <T> T deserialize(byte[] data, TypeRef<T> type) throws IOException {
        try {
            JavaType javaType = objectMapper.getTypeFactory().constructType(type.getType());
            return objectMapper.readValue(data, javaType);
        } catch (IOException e) {
            throw new DaprException(e);
        }
    }

    @Override
    public String getContentType() {
        return "application/json";
    }

}

Added this custom serializer for building dapr client instance :

DaprObjectSerializer serializer = new JacksonDaprObjectSerializer(new ObjectMapper());

DaprClient client = (new DaprClientBuilder())
                    .withObjectSerializer(serializer) // for request/response objects.
                    .withStateSerializer(serializer) // for state objects.
                    .build();

This fixed the issue!