From aa33ad4573c17676ed9845dd425e11cfee13b23e Mon Sep 17 00:00:00 2001 From: Francesco Guardiani Date: Fri, 26 Jul 2024 16:44:47 +0200 Subject: [PATCH] Fix wrong nullability hint in `AwakeableHandle#resolve` (#361) * Fix Serde nullability annotations * Bump JSpecify to 1.0 --- .../java/dev/restate/sdk/AwakeableHandle.java | 3 +- .../main/java/dev/restate/sdk/JsonSerdes.java | 22 ++++++------- .../java/dev/restate/sdk/common/Serde.java | 32 +++++++++---------- .../sdk/serde/jackson/JacksonSerdes.java | 5 ++- settings.gradle.kts | 2 +- 5 files changed, 31 insertions(+), 33 deletions(-) diff --git a/sdk-api/src/main/java/dev/restate/sdk/AwakeableHandle.java b/sdk-api/src/main/java/dev/restate/sdk/AwakeableHandle.java index d335564b..eb8a8ecf 100644 --- a/sdk-api/src/main/java/dev/restate/sdk/AwakeableHandle.java +++ b/sdk-api/src/main/java/dev/restate/sdk/AwakeableHandle.java @@ -9,7 +9,6 @@ package dev.restate.sdk; import dev.restate.sdk.common.Serde; -import org.jspecify.annotations.NonNull; /** This class represents a handle to an {@link Awakeable} created in another service. */ public interface AwakeableHandle { @@ -21,7 +20,7 @@ public interface AwakeableHandle { * @param payload the result payload. MUST NOT be null. * @see Awakeable */ - void resolve(Serde serde, @NonNull T payload); + void resolve(Serde serde, T payload); /** * Complete with failure the {@link Awakeable}. diff --git a/sdk-api/src/main/java/dev/restate/sdk/JsonSerdes.java b/sdk-api/src/main/java/dev/restate/sdk/JsonSerdes.java index f13d1b1d..18d9cc57 100644 --- a/sdk-api/src/main/java/dev/restate/sdk/JsonSerdes.java +++ b/sdk-api/src/main/java/dev/restate/sdk/JsonSerdes.java @@ -18,7 +18,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; -import org.jspecify.annotations.Nullable; +import org.jspecify.annotations.NonNull; /** * Collection of common serializers/deserializers. @@ -30,7 +30,7 @@ public abstract class JsonSerdes { private JsonSerdes() {} /** {@link Serde} for {@link String}. This writes and reads {@link String} as JSON value. */ - public static Serde STRING = + public static Serde<@NonNull String> STRING = usingJackson( JsonGenerator::writeString, p -> { @@ -42,7 +42,7 @@ private JsonSerdes() {} }); /** {@link Serde} for {@link Boolean}. This writes and reads {@link Boolean} as JSON value. */ - public static Serde BOOLEAN = + public static Serde<@NonNull Boolean> BOOLEAN = usingJackson( JsonGenerator::writeBoolean, p -> { @@ -51,7 +51,7 @@ private JsonSerdes() {} }); /** {@link Serde} for {@link Byte}. This writes and reads {@link Byte} as JSON value. */ - public static Serde BYTE = + public static Serde<@NonNull Byte> BYTE = usingJackson( JsonGenerator::writeNumber, p -> { @@ -60,7 +60,7 @@ private JsonSerdes() {} }); /** {@link Serde} for {@link Short}. This writes and reads {@link Short} as JSON value. */ - public static Serde SHORT = + public static Serde<@NonNull Short> SHORT = usingJackson( JsonGenerator::writeNumber, p -> { @@ -69,7 +69,7 @@ private JsonSerdes() {} }); /** {@link Serde} for {@link Integer}. This writes and reads {@link Integer} as JSON value. */ - public static Serde INT = + public static Serde<@NonNull Integer> INT = usingJackson( JsonGenerator::writeNumber, p -> { @@ -78,7 +78,7 @@ private JsonSerdes() {} }); /** {@link Serde} for {@link Long}. This writes and reads {@link Long} as JSON value. */ - public static Serde LONG = + public static Serde<@NonNull Long> LONG = usingJackson( JsonGenerator::writeNumber, p -> { @@ -87,7 +87,7 @@ private JsonSerdes() {} }); /** {@link Serde} for {@link Float}. This writes and reads {@link Float} as JSON value. */ - public static Serde FLOAT = + public static Serde<@NonNull Float> FLOAT = usingJackson( JsonGenerator::writeNumber, p -> { @@ -96,7 +96,7 @@ private JsonSerdes() {} }); /** {@link Serde} for {@link Double}. This writes and reads {@link Double} as JSON value. */ - public static Serde DOUBLE = + public static Serde<@NonNull Double> DOUBLE = usingJackson( JsonGenerator::writeNumber, p -> { @@ -108,12 +108,12 @@ private JsonSerdes() {} private static final JsonFactory JSON_FACTORY = new JsonFactory(); - private static Serde usingJackson( + private static Serde usingJackson( ThrowingBiConsumer serializer, ThrowingFunction deserializer) { return new Serde<>() { @Override - public byte[] serialize(@Nullable T value) { + public byte[] serialize(T value) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try (JsonGenerator gen = JSON_FACTORY.createGenerator(outputStream)) { serializer.asBiConsumer().accept(gen, value); diff --git a/sdk-common/src/main/java/dev/restate/sdk/common/Serde.java b/sdk-common/src/main/java/dev/restate/sdk/common/Serde.java index 4b0fd474..042893fb 100644 --- a/sdk-common/src/main/java/dev/restate/sdk/common/Serde.java +++ b/sdk-common/src/main/java/dev/restate/sdk/common/Serde.java @@ -11,7 +11,7 @@ import dev.restate.sdk.common.function.ThrowingFunction; import java.nio.ByteBuffer; import java.util.Objects; -import org.jspecify.annotations.Nullable; +import org.jspecify.annotations.*; /** * Interface defining serialization and deserialization of concrete types. @@ -22,11 +22,12 @@ * *

You can create a custom one using {@link #using(String, ThrowingFunction, ThrowingFunction)}. */ -public interface Serde { +@NullMarked +public interface Serde { - byte[] serialize(@Nullable T value); + byte[] serialize(T value); - default ByteBuffer serializeToByteBuffer(@Nullable T value) { + default ByteBuffer serializeToByteBuffer(T value) { // This is safe because we don't mutate the generated byte[] afterward. return ByteBuffer.wrap(serialize(value)); } @@ -57,7 +58,7 @@ default T deserialize(ByteBuffer byteBuffer) { * Like {@link #using(String, ThrowingFunction, ThrowingFunction)}, using content-type {@code * application/octet-stream}. */ - static Serde using( + static Serde<@NonNull T> using( ThrowingFunction serializer, ThrowingFunction deserializer) { return new Serde<>() { @Override @@ -76,7 +77,7 @@ public T deserialize(byte[] value) { * Create a {@link Serde} from {@code serializer}/{@code deserializer} lambdas, tagging with * {@code contentType}. Before invoking the serializer, we check that {@code value} is non-null. */ - static Serde using( + static Serde<@NonNull T> using( String contentType, ThrowingFunction serializer, ThrowingFunction deserializer) { @@ -92,7 +93,7 @@ public T deserialize(byte[] value) { } @Override - public @Nullable String contentType() { + public String contentType() { return contentType; } }; @@ -101,12 +102,12 @@ public T deserialize(byte[] value) { static Serde withContentType(String contentType, Serde inner) { return new Serde<>() { @Override - public byte[] serialize(@Nullable T value) { + public byte[] serialize(T value) { return inner.serialize(value); } @Override - public ByteBuffer serializeToByteBuffer(@Nullable T value) { + public ByteBuffer serializeToByteBuffer(T value) { return inner.serializeToByteBuffer(value); } @@ -121,14 +122,14 @@ public T deserialize(byte[] value) { } @Override - public @Nullable String contentType() { + public String contentType() { return contentType; } }; } /** Noop {@link Serde} for void. */ - Serde VOID = + Serde<@Nullable Void> VOID = new Serde<>() { @Override public byte[] serialize(Void value) { @@ -136,7 +137,7 @@ public byte[] serialize(Void value) { } @Override - public ByteBuffer serializeToByteBuffer(@Nullable Void value) { + public ByteBuffer serializeToByteBuffer(Void value) { return ByteBuffer.allocate(0); } @@ -151,7 +152,7 @@ public Void deserialize(ByteBuffer byteBuffer) { } @Override - public @Nullable String contentType() { + public String contentType() { return null; } }; @@ -173,9 +174,8 @@ public byte[] deserialize(byte[] value) { /** Pass through {@link Serde} for {@link ByteBuffer}. */ Serde BYTE_BUFFER = new Serde<>() { - @Override - public byte[] serialize(@Nullable ByteBuffer byteBuffer) { + public byte[] serialize(ByteBuffer byteBuffer) { if (byteBuffer == null) { return new byte[] {}; } @@ -188,7 +188,7 @@ public byte[] serialize(@Nullable ByteBuffer byteBuffer) { } @Override - public ByteBuffer serializeToByteBuffer(@Nullable ByteBuffer value) { + public ByteBuffer serializeToByteBuffer(ByteBuffer value) { return value; } diff --git a/sdk-serde-jackson/src/main/java/dev/restate/sdk/serde/jackson/JacksonSerdes.java b/sdk-serde-jackson/src/main/java/dev/restate/sdk/serde/jackson/JacksonSerdes.java index 52e9d80d..08b134d1 100644 --- a/sdk-serde-jackson/src/main/java/dev/restate/sdk/serde/jackson/JacksonSerdes.java +++ b/sdk-serde-jackson/src/main/java/dev/restate/sdk/serde/jackson/JacksonSerdes.java @@ -13,7 +13,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import dev.restate.sdk.common.Serde; import java.io.IOException; -import org.jspecify.annotations.Nullable; /** * {@link Serde} implementations for Jackson. @@ -57,7 +56,7 @@ public static Serde of(Class clazz) { public static Serde of(ObjectMapper mapper, Class clazz) { return new Serde<>() { @Override - public byte[] serialize(@Nullable T value) { + public byte[] serialize(T value) { try { return mapper.writeValueAsBytes(value); } catch (JsonProcessingException e) { @@ -92,7 +91,7 @@ public static Serde of(TypeReference typeReference) { public static Serde of(ObjectMapper mapper, TypeReference typeReference) { return new Serde<>() { @Override - public byte[] serialize(@Nullable T value) { + public byte[] serialize(T value) { try { return mapper.writeValueAsBytes(value); } catch (JsonProcessingException e) { diff --git a/settings.gradle.kts b/settings.gradle.kts index 2398d547..40c681ef 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -51,7 +51,7 @@ dependencyResolutionManagement { library("opentelemetry-kotlin", "io.opentelemetry", "opentelemetry-extension-kotlin") .withoutVersion() - library("jspecify", "org.jspecify", "jspecify").version("0.3.0") + library("jspecify", "org.jspecify", "jspecify").version("1.0.0") library("jwt", "com.nimbusds:nimbus-jose-jwt:9.37.3") library("tink", "com.google.crypto.tink:tink:1.13.0")