From c58b9b3bca64cff638deb1553388bf4a3fb1b082 Mon Sep 17 00:00:00 2001 From: Andrey Bogdanov Date: Tue, 9 Mar 2021 16:10:23 +0300 Subject: [PATCH 1/6] Refactor ObjectSerializer class to add ability set custom object mapper. Refactor DaprStateAsyncprovider class to use custom serializers based on ObjectSerializer class as Json serializer. Add unit tests. --- .../actors/runtime/ActorObjectSerializer.java | 4 +- .../runtime/DaprStateAsyncProvider.java | 3 +- .../runtime/DaprStateAsyncProviderTest.java | 57 ++++++++++++++++++- .../java/io/dapr/client/ObjectSerializer.java | 38 ++++++++----- 4 files changed, 85 insertions(+), 17 deletions(-) diff --git a/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorObjectSerializer.java b/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorObjectSerializer.java index d45bd78d5..e70b0bd4b 100644 --- a/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorObjectSerializer.java +++ b/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorObjectSerializer.java @@ -174,7 +174,7 @@ public class ActorObjectSerializer extends ObjectSerializer { return null; } - JsonNode node = OBJECT_MAPPER.readTree(value); + JsonNode node = getObjectMapper().readTree(value); String callback = node.get("callback").asText(); Duration dueTime = extractDurationOrNull(node, "dueTime"); Duration period = extractDurationOrNull(node, "period"); @@ -195,7 +195,7 @@ public class ActorObjectSerializer extends ObjectSerializer { return null; } - JsonNode node = OBJECT_MAPPER.readTree(value); + JsonNode node = getObjectMapper().readTree(value); Duration dueTime = extractDurationOrNull(node, "dueTime"); Duration period = extractDurationOrNull(node, "period"); byte[] data = node.get("data") != null ? node.get("data").binaryValue() : null; diff --git a/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java b/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java index 3aa2f09ec..6e9106da1 100644 --- a/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java +++ b/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java @@ -7,6 +7,7 @@ package io.dapr.actors.runtime; import com.fasterxml.jackson.databind.ObjectMapper; import io.dapr.actors.ActorId; +import io.dapr.client.ObjectSerializer; import io.dapr.config.Properties; import io.dapr.serializer.DaprObjectSerializer; import io.dapr.serializer.DefaultObjectSerializer; @@ -56,7 +57,7 @@ class DaprStateAsyncProvider { DaprStateAsyncProvider(DaprClient daprClient, DaprObjectSerializer stateSerializer) { this.daprClient = daprClient; this.stateSerializer = stateSerializer; - this.isStateSerializerDefault = stateSerializer.getClass() == DefaultObjectSerializer.class; + this.isStateSerializerDefault = ObjectSerializer.class.isAssignableFrom(stateSerializer.getClass()); } Mono load(String actorType, ActorId actorId, String stateName, TypeRef type) { diff --git a/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java b/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java index 3b8a27320..238f418f9 100644 --- a/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java +++ b/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java @@ -7,6 +7,7 @@ package io.dapr.actors.runtime; import com.fasterxml.jackson.databind.ObjectMapper; import io.dapr.actors.ActorId; +import io.dapr.client.ObjectSerializer; import io.dapr.serializer.DaprObjectSerializer; import io.dapr.serializer.DefaultObjectSerializer; import io.dapr.utils.TypeRef; @@ -31,6 +32,17 @@ public class DaprStateAsyncProviderTest { private static final double EPSILON = 1e-10; + class CustomJsonSerializer extends ObjectSerializer implements DaprObjectSerializer{ + CustomJsonSerializer() { + super(DaprStateAsyncProviderTest.OBJECT_MAPPER); + } + + @Override + public String getContentType() { + return "application/json"; + } + } + /** * Class used to test JSON serialization. */ @@ -124,7 +136,7 @@ public class DaprStateAsyncProviderTest { }))) .thenReturn(Mono.empty()); - DaprStateAsyncProvider provider = new DaprStateAsyncProvider(daprClient, SERIALIZER); + DaprStateAsyncProvider provider = new DaprStateAsyncProvider(daprClient, new CustomJsonSerializer()); provider.apply("MyActor", new ActorId("123"), createInsertChange("name", "Jon Doe"), @@ -136,6 +148,49 @@ public class DaprStateAsyncProviderTest { verify(daprClient).saveStateTransactionally(eq("MyActor"), eq("123"), any()); } + @Test + public void happyCaseApplyWithCustomJsonSerializer() { + DaprClient daprClient = mock(DaprClient.class); + when(daprClient + .saveStateTransactionally( + eq("MyActor"), + eq("123"), + argThat(operations -> { + if (operations == null) { + return false; + } + + if (operations.size() != 1) { + return false; + } + ActorStateOperation operation = operations.get(0); + if (operation.getOperationType() == null) { + return false; + } + if (operation.getKey() == null) { + return false; + } + + String opName = operation.getOperationType(); + String key = operation.getKey(); + Object value = operation.getValue(); + + return "upsert".equals(opName) && + "object".equals(key) && + "{\"id\":1000,\"name\":\"Roxane\"}".equals(value); + }))) + .thenReturn(Mono.empty()); + + DaprStateAsyncProvider provider = new DaprStateAsyncProvider(daprClient, SERIALIZER); + provider.apply("MyActor", + new ActorId("123"), + createInsertChange("object", new Customer().setId(1000).setName("Roxane"))) + .block(); + + verify(daprClient).saveStateTransactionally(eq("MyActor"), eq("123"), any()); + } + + @Test public void happyCaseLoad() throws Exception { DaprClient daprClient = mock(DaprClient.class); diff --git a/sdk/src/main/java/io/dapr/client/ObjectSerializer.java b/sdk/src/main/java/io/dapr/client/ObjectSerializer.java index 0f1c452a7..323055479 100644 --- a/sdk/src/main/java/io/dapr/client/ObjectSerializer.java +++ b/sdk/src/main/java/io/dapr/client/ObjectSerializer.java @@ -22,17 +22,22 @@ import java.lang.reflect.Method; */ public class ObjectSerializer { - /** - * Shared Json serializer/deserializer as per Jackson's documentation. - */ - protected static final ObjectMapper OBJECT_MAPPER = new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .setSerializationInclusion(JsonInclude.Include.NON_NULL); + private final ObjectMapper objectMapper; /** * Default constructor to avoid class from being instantiated outside package but still inherited. */ protected ObjectSerializer() { + objectMapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .setSerializationInclusion(JsonInclude.Include.NON_NULL); + } + + /** + * Default constructor to avoid class from being instantiated outside package but still inherited. + */ + protected ObjectSerializer(ObjectMapper mapper) { + objectMapper = mapper; } /** @@ -62,7 +67,7 @@ public class ObjectSerializer { } // Not string, not primitive, so it is a complex type: we use JSON for that. - return OBJECT_MAPPER.writeValueAsBytes(state); + return getObjectMapper().writeValueAsBytes(state); } /** @@ -75,7 +80,7 @@ public class ObjectSerializer { * @throws IOException In case content cannot be deserialized. */ public T deserialize(byte[] content, TypeRef type) throws IOException { - return deserialize(content, OBJECT_MAPPER.constructType(type.getType())); + return deserialize(content, getObjectMapper().constructType(type.getType())); } /** @@ -88,7 +93,7 @@ public class ObjectSerializer { * @throws IOException In case content cannot be deserialized. */ public T deserialize(byte[] content, Class clazz) throws IOException { - return deserialize(content, OBJECT_MAPPER.constructType(clazz)); + return deserialize(content, getObjectMapper().constructType(clazz)); } private T deserialize(byte[] content, JavaType javaType) throws IOException { @@ -130,7 +135,7 @@ public class ObjectSerializer { } } - return OBJECT_MAPPER.readValue(content, javaType); + return getObjectMapper().readValue(content, javaType); } /** @@ -141,7 +146,7 @@ public class ObjectSerializer { * @throws IOException In case content cannot be parsed. */ public JsonNode parseNode(byte[] content) throws IOException { - return OBJECT_MAPPER.readTree(content); + return getObjectMapper().readTree(content); } /** @@ -153,7 +158,7 @@ public class ObjectSerializer { * @return Result as corresponding type. * @throws IOException if cannot deserialize primitive time. */ - private static T deserializePrimitives(byte[] content, JavaType javaType) throws IOException { + private T deserializePrimitives(byte[] content, JavaType javaType) throws IOException { if ((content == null) || (content.length == 0)) { if (javaType.hasRawClass(boolean.class)) { return (T) Boolean.FALSE; @@ -190,6 +195,13 @@ public class ObjectSerializer { return null; } - return OBJECT_MAPPER.readValue(content, javaType); + return getObjectMapper().readValue(content, javaType); + } + + /** + * Shared Json serializer/deserializer as per Jackson's documentation. + */ + protected ObjectMapper getObjectMapper() { + return objectMapper; } } From 6bfd6844bc8383c1c296e5b18021c76d302482f0 Mon Sep 17 00:00:00 2001 From: Andrey Bogdanov Date: Wed, 10 Mar 2021 14:12:30 +0300 Subject: [PATCH 2/6] Up test coverage. --- .../CustomJsonObjectSerializerTest.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 sdk/src/test/java/io/dapr/serializer/CustomJsonObjectSerializerTest.java diff --git a/sdk/src/test/java/io/dapr/serializer/CustomJsonObjectSerializerTest.java b/sdk/src/test/java/io/dapr/serializer/CustomJsonObjectSerializerTest.java new file mode 100644 index 000000000..3f93f76a6 --- /dev/null +++ b/sdk/src/test/java/io/dapr/serializer/CustomJsonObjectSerializerTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) Microsoft Corporation and Dapr Contributors. + * Licensed under the MIT License. + */ + +package io.dapr.serializer; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.dapr.client.ObjectSerializer; +import io.dapr.utils.TypeRef; +import org.junit.Test; + +import java.io.IOException; +import java.lang.reflect.Type; + +import static org.junit.Assert.*; + +public class CustomJsonObjectSerializerTest { + + public static class CustomJsonSerializer extends ObjectSerializer implements DaprObjectSerializer { + CustomJsonSerializer() { + super(new ObjectMapper()); + } + + public ObjectMapper getObjectMapper() { + return super.getObjectMapper(); + } + + @Override + public String getContentType() { + return "application/json"; + } + } + + CustomJsonSerializer SERIALIZER = new CustomJsonSerializer(); + + @Test + public void serializeObjectTest() { + DefaultObjectSerializerTest.MyObjectTestToSerialize obj = new DefaultObjectSerializerTest.MyObjectTestToSerialize(); + obj.setStringValue("A String"); + obj.setIntValue(2147483647); + obj.setBoolValue(true); + obj.setCharValue('a'); + obj.setByteValue((byte) 65); + obj.setShortValue((short) 32767); + obj.setLongValue(9223372036854775807L); + obj.setFloatValue(1.0f); + obj.setDoubleValue(1000.0); + //String expectedResult = "{\"stringValue\":\"A String\",\"intValue\":2147483647,\"boolValue\":true,\"charValue\":\"a\",\"byteValue\":65,\"shortValue\":32767,\"longValue\":9223372036854775807,\"floatValue\":1.0,\"doubleValue\":1000.0}"; + + byte[] serializedValue; + try { + serializedValue = SERIALIZER.serialize(obj); + assertNotNull(serializedValue); + DefaultObjectSerializerTest.MyObjectTestToSerialize deserializedValue = SERIALIZER.deserialize(serializedValue, DefaultObjectSerializerTest.MyObjectTestToSerialize.class); + assertEquals(obj, deserializedValue); + } catch (IOException exception) { + fail(exception.getMessage()); + } + + try { + serializedValue = SERIALIZER.serialize(obj); + assertNotNull(serializedValue); + Type t = DefaultObjectSerializerTest.MyObjectTestToSerialize.class; + TypeRef tr = TypeRef.get(t); + DefaultObjectSerializerTest.MyObjectTestToSerialize deserializedValue = SERIALIZER.deserialize(serializedValue, tr); + assertEquals(obj, deserializedValue); + } catch (IOException exception) { + fail(exception.getMessage()); + } + + assertNotNull(SERIALIZER.getObjectMapper()); + } + +} From 4c0d043fb400183c3b5990596f81b5eb74f0d8c0 Mon Sep 17 00:00:00 2001 From: Andrey Bogdanov Date: Wed, 10 Mar 2021 15:42:09 +0300 Subject: [PATCH 3/6] Change strategy to find Json serializer by content type --- .../io/dapr/actors/runtime/DaprStateAsyncProvider.java | 8 ++++---- .../dapr/actors/runtime/DaprStateAsyncProviderTest.java | 2 +- .../java/io/dapr/serializer/DefaultObjectSerializer.java | 4 +++- .../dapr/serializer/CustomJsonObjectSerializerTest.java | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java b/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java index 6e9106da1..28b6a2594 100644 --- a/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java +++ b/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java @@ -46,7 +46,7 @@ class DaprStateAsyncProvider { /** * Flag determining if state serializer is the default serializer instead of user provided. */ - private final boolean isStateSerializerDefault; + private final boolean isStateSerializerJson; /** * Instantiates a new Actor's state provider. @@ -57,7 +57,7 @@ class DaprStateAsyncProvider { DaprStateAsyncProvider(DaprClient daprClient, DaprObjectSerializer stateSerializer) { this.daprClient = daprClient; this.stateSerializer = stateSerializer; - this.isStateSerializerDefault = ObjectSerializer.class.isAssignableFrom(stateSerializer.getClass()); + this.isStateSerializerJson = DefaultObjectSerializer.JSON_CONTENT_TYPE.equals(stateSerializer.getContentType()); } Mono load(String actorType, ActorId actorId, String stateName, TypeRef type) { @@ -70,7 +70,7 @@ class DaprStateAsyncProvider { } T response = this.stateSerializer.deserialize(s, type); - if (this.isStateSerializerDefault && (response instanceof byte[])) { + if (this.isStateSerializerJson && (response instanceof byte[])) { if (s.length == 0) { return Mono.empty(); } @@ -139,7 +139,7 @@ class DaprStateAsyncProvider { try { byte[] data = this.stateSerializer.serialize(stateChange.getValue()); if (data != null) { - if (this.isStateSerializerDefault && !(stateChange.getValue() instanceof byte[])) { + if (this.isStateSerializerJson && !(stateChange.getValue() instanceof byte[])) { // DefaultObjectSerializer is a JSON serializer, so we just pass it on. value = new String(data, CHARSET); } else { diff --git a/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java b/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java index 238f418f9..720a28461 100644 --- a/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java +++ b/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java @@ -39,7 +39,7 @@ public class DaprStateAsyncProviderTest { @Override public String getContentType() { - return "application/json"; + return DefaultObjectSerializer.JSON_CONTENT_TYPE; } } diff --git a/sdk/src/main/java/io/dapr/serializer/DefaultObjectSerializer.java b/sdk/src/main/java/io/dapr/serializer/DefaultObjectSerializer.java index b2c789446..6ef9860ea 100644 --- a/sdk/src/main/java/io/dapr/serializer/DefaultObjectSerializer.java +++ b/sdk/src/main/java/io/dapr/serializer/DefaultObjectSerializer.java @@ -15,6 +15,8 @@ import java.io.IOException; */ public class DefaultObjectSerializer extends ObjectSerializer implements DaprObjectSerializer { + public static final String JSON_CONTENT_TYPE = "application/json"; + /** * {@inheritDoc} */ @@ -36,6 +38,6 @@ public class DefaultObjectSerializer extends ObjectSerializer implements DaprObj */ @Override public String getContentType() { - return "application/json"; + return JSON_CONTENT_TYPE; } } diff --git a/sdk/src/test/java/io/dapr/serializer/CustomJsonObjectSerializerTest.java b/sdk/src/test/java/io/dapr/serializer/CustomJsonObjectSerializerTest.java index 3f93f76a6..de0beaecd 100644 --- a/sdk/src/test/java/io/dapr/serializer/CustomJsonObjectSerializerTest.java +++ b/sdk/src/test/java/io/dapr/serializer/CustomJsonObjectSerializerTest.java @@ -28,7 +28,7 @@ public class CustomJsonObjectSerializerTest { @Override public String getContentType() { - return "application/json"; + return DefaultObjectSerializer.JSON_CONTENT_TYPE; } } From a3c7056be2b852bbecd8c8b82c8a7e428bf4fbd0 Mon Sep 17 00:00:00 2001 From: Andrey Bogdanov Date: Thu, 11 Mar 2021 09:52:57 +0300 Subject: [PATCH 4/6] Revert changes with ObjectSerializer class. --- .../runtime/DaprStateAsyncProvider.java | 4 +- .../runtime/DaprStateAsyncProviderTest.java | 21 ++++-- .../java/io/dapr/client/ObjectSerializer.java | 38 ++++------ .../serializer/DefaultObjectSerializer.java | 4 +- .../CustomJsonObjectSerializerTest.java | 75 ------------------- 5 files changed, 32 insertions(+), 110 deletions(-) delete mode 100644 sdk/src/test/java/io/dapr/serializer/CustomJsonObjectSerializerTest.java diff --git a/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java b/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java index 28b6a2594..dfd8e92ab 100644 --- a/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java +++ b/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java @@ -28,6 +28,8 @@ class DaprStateAsyncProvider { */ private static final Charset CHARSET = Properties.STRING_CHARSET.get(); + public static final String JSON_CONTENT_TYPE = "application/json"; + /** * Handles special serialization cases. */ @@ -57,7 +59,7 @@ class DaprStateAsyncProvider { DaprStateAsyncProvider(DaprClient daprClient, DaprObjectSerializer stateSerializer) { this.daprClient = daprClient; this.stateSerializer = stateSerializer; - this.isStateSerializerJson = DefaultObjectSerializer.JSON_CONTENT_TYPE.equals(stateSerializer.getContentType()); + this.isStateSerializerJson = JSON_CONTENT_TYPE.equals(stateSerializer.getContentType()); } Mono load(String actorType, ActorId actorId, String stateName, TypeRef type) { diff --git a/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java b/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java index 720a28461..caf53d127 100644 --- a/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java +++ b/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java @@ -15,6 +15,7 @@ import org.junit.Assert; import org.junit.Test; import reactor.core.publisher.Mono; +import java.io.IOException; import java.util.Arrays; import java.util.Objects; @@ -28,18 +29,26 @@ public class DaprStateAsyncProviderTest { private static final DaprObjectSerializer SERIALIZER = new DefaultObjectSerializer(); - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private static final double EPSILON = 1e-10; - class CustomJsonSerializer extends ObjectSerializer implements DaprObjectSerializer{ - CustomJsonSerializer() { - super(DaprStateAsyncProviderTest.OBJECT_MAPPER); - } + class CustomJsonSerializer implements DaprObjectSerializer{ + private final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + @Override + public byte[] serialize(Object o) throws IOException { + return OBJECT_MAPPER.writeValueAsBytes(o); + } + + @Override + public T deserialize(byte[] data, TypeRef type) throws IOException { + return OBJECT_MAPPER.readValue(data, OBJECT_MAPPER.constructType(type.getType())); + } @Override public String getContentType() { - return DefaultObjectSerializer.JSON_CONTENT_TYPE; + return "application/json"; } } diff --git a/sdk/src/main/java/io/dapr/client/ObjectSerializer.java b/sdk/src/main/java/io/dapr/client/ObjectSerializer.java index 323055479..0f1c452a7 100644 --- a/sdk/src/main/java/io/dapr/client/ObjectSerializer.java +++ b/sdk/src/main/java/io/dapr/client/ObjectSerializer.java @@ -22,22 +22,17 @@ import java.lang.reflect.Method; */ public class ObjectSerializer { - private final ObjectMapper objectMapper; + /** + * Shared Json serializer/deserializer as per Jackson's documentation. + */ + protected static final ObjectMapper OBJECT_MAPPER = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .setSerializationInclusion(JsonInclude.Include.NON_NULL); /** * Default constructor to avoid class from being instantiated outside package but still inherited. */ protected ObjectSerializer() { - objectMapper = new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .setSerializationInclusion(JsonInclude.Include.NON_NULL); - } - - /** - * Default constructor to avoid class from being instantiated outside package but still inherited. - */ - protected ObjectSerializer(ObjectMapper mapper) { - objectMapper = mapper; } /** @@ -67,7 +62,7 @@ public class ObjectSerializer { } // Not string, not primitive, so it is a complex type: we use JSON for that. - return getObjectMapper().writeValueAsBytes(state); + return OBJECT_MAPPER.writeValueAsBytes(state); } /** @@ -80,7 +75,7 @@ public class ObjectSerializer { * @throws IOException In case content cannot be deserialized. */ public T deserialize(byte[] content, TypeRef type) throws IOException { - return deserialize(content, getObjectMapper().constructType(type.getType())); + return deserialize(content, OBJECT_MAPPER.constructType(type.getType())); } /** @@ -93,7 +88,7 @@ public class ObjectSerializer { * @throws IOException In case content cannot be deserialized. */ public T deserialize(byte[] content, Class clazz) throws IOException { - return deserialize(content, getObjectMapper().constructType(clazz)); + return deserialize(content, OBJECT_MAPPER.constructType(clazz)); } private T deserialize(byte[] content, JavaType javaType) throws IOException { @@ -135,7 +130,7 @@ public class ObjectSerializer { } } - return getObjectMapper().readValue(content, javaType); + return OBJECT_MAPPER.readValue(content, javaType); } /** @@ -146,7 +141,7 @@ public class ObjectSerializer { * @throws IOException In case content cannot be parsed. */ public JsonNode parseNode(byte[] content) throws IOException { - return getObjectMapper().readTree(content); + return OBJECT_MAPPER.readTree(content); } /** @@ -158,7 +153,7 @@ public class ObjectSerializer { * @return Result as corresponding type. * @throws IOException if cannot deserialize primitive time. */ - private T deserializePrimitives(byte[] content, JavaType javaType) throws IOException { + private static T deserializePrimitives(byte[] content, JavaType javaType) throws IOException { if ((content == null) || (content.length == 0)) { if (javaType.hasRawClass(boolean.class)) { return (T) Boolean.FALSE; @@ -195,13 +190,6 @@ public class ObjectSerializer { return null; } - return getObjectMapper().readValue(content, javaType); - } - - /** - * Shared Json serializer/deserializer as per Jackson's documentation. - */ - protected ObjectMapper getObjectMapper() { - return objectMapper; + return OBJECT_MAPPER.readValue(content, javaType); } } diff --git a/sdk/src/main/java/io/dapr/serializer/DefaultObjectSerializer.java b/sdk/src/main/java/io/dapr/serializer/DefaultObjectSerializer.java index 6ef9860ea..b2c789446 100644 --- a/sdk/src/main/java/io/dapr/serializer/DefaultObjectSerializer.java +++ b/sdk/src/main/java/io/dapr/serializer/DefaultObjectSerializer.java @@ -15,8 +15,6 @@ import java.io.IOException; */ public class DefaultObjectSerializer extends ObjectSerializer implements DaprObjectSerializer { - public static final String JSON_CONTENT_TYPE = "application/json"; - /** * {@inheritDoc} */ @@ -38,6 +36,6 @@ public class DefaultObjectSerializer extends ObjectSerializer implements DaprObj */ @Override public String getContentType() { - return JSON_CONTENT_TYPE; + return "application/json"; } } diff --git a/sdk/src/test/java/io/dapr/serializer/CustomJsonObjectSerializerTest.java b/sdk/src/test/java/io/dapr/serializer/CustomJsonObjectSerializerTest.java deleted file mode 100644 index de0beaecd..000000000 --- a/sdk/src/test/java/io/dapr/serializer/CustomJsonObjectSerializerTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation and Dapr Contributors. - * Licensed under the MIT License. - */ - -package io.dapr.serializer; - -import com.fasterxml.jackson.databind.ObjectMapper; -import io.dapr.client.ObjectSerializer; -import io.dapr.utils.TypeRef; -import org.junit.Test; - -import java.io.IOException; -import java.lang.reflect.Type; - -import static org.junit.Assert.*; - -public class CustomJsonObjectSerializerTest { - - public static class CustomJsonSerializer extends ObjectSerializer implements DaprObjectSerializer { - CustomJsonSerializer() { - super(new ObjectMapper()); - } - - public ObjectMapper getObjectMapper() { - return super.getObjectMapper(); - } - - @Override - public String getContentType() { - return DefaultObjectSerializer.JSON_CONTENT_TYPE; - } - } - - CustomJsonSerializer SERIALIZER = new CustomJsonSerializer(); - - @Test - public void serializeObjectTest() { - DefaultObjectSerializerTest.MyObjectTestToSerialize obj = new DefaultObjectSerializerTest.MyObjectTestToSerialize(); - obj.setStringValue("A String"); - obj.setIntValue(2147483647); - obj.setBoolValue(true); - obj.setCharValue('a'); - obj.setByteValue((byte) 65); - obj.setShortValue((short) 32767); - obj.setLongValue(9223372036854775807L); - obj.setFloatValue(1.0f); - obj.setDoubleValue(1000.0); - //String expectedResult = "{\"stringValue\":\"A String\",\"intValue\":2147483647,\"boolValue\":true,\"charValue\":\"a\",\"byteValue\":65,\"shortValue\":32767,\"longValue\":9223372036854775807,\"floatValue\":1.0,\"doubleValue\":1000.0}"; - - byte[] serializedValue; - try { - serializedValue = SERIALIZER.serialize(obj); - assertNotNull(serializedValue); - DefaultObjectSerializerTest.MyObjectTestToSerialize deserializedValue = SERIALIZER.deserialize(serializedValue, DefaultObjectSerializerTest.MyObjectTestToSerialize.class); - assertEquals(obj, deserializedValue); - } catch (IOException exception) { - fail(exception.getMessage()); - } - - try { - serializedValue = SERIALIZER.serialize(obj); - assertNotNull(serializedValue); - Type t = DefaultObjectSerializerTest.MyObjectTestToSerialize.class; - TypeRef tr = TypeRef.get(t); - DefaultObjectSerializerTest.MyObjectTestToSerialize deserializedValue = SERIALIZER.deserialize(serializedValue, tr); - assertEquals(obj, deserializedValue); - } catch (IOException exception) { - fail(exception.getMessage()); - } - - assertNotNull(SERIALIZER.getObjectMapper()); - } - -} From 9bf4adeae5de632120cab77e56644e044f1f70ad Mon Sep 17 00:00:00 2001 From: Andrey Bogdanov Date: Thu, 11 Mar 2021 09:54:44 +0300 Subject: [PATCH 5/6] Revert changes with ObjectSerializer class. --- .../java/io/dapr/actors/runtime/ActorObjectSerializer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorObjectSerializer.java b/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorObjectSerializer.java index e70b0bd4b..d45bd78d5 100644 --- a/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorObjectSerializer.java +++ b/sdk-actors/src/main/java/io/dapr/actors/runtime/ActorObjectSerializer.java @@ -174,7 +174,7 @@ public class ActorObjectSerializer extends ObjectSerializer { return null; } - JsonNode node = getObjectMapper().readTree(value); + JsonNode node = OBJECT_MAPPER.readTree(value); String callback = node.get("callback").asText(); Duration dueTime = extractDurationOrNull(node, "dueTime"); Duration period = extractDurationOrNull(node, "period"); @@ -195,7 +195,7 @@ public class ActorObjectSerializer extends ObjectSerializer { return null; } - JsonNode node = getObjectMapper().readTree(value); + JsonNode node = OBJECT_MAPPER.readTree(value); Duration dueTime = extractDurationOrNull(node, "dueTime"); Duration period = extractDurationOrNull(node, "period"); byte[] data = node.get("data") != null ? node.get("data").binaryValue() : null; From db97c19bd0791cb6d0078c809fe003996cc20c49 Mon Sep 17 00:00:00 2001 From: Andrey Bogdanov Date: Thu, 11 Mar 2021 10:23:55 +0300 Subject: [PATCH 6/6] Fix unit tests. Add comments. --- .../java/io/dapr/actors/runtime/DaprStateAsyncProvider.java | 5 +++-- .../io/dapr/actors/runtime/DaprStateAsyncProviderTest.java | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java b/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java index dfd8e92ab..b365adb00 100644 --- a/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java +++ b/sdk-actors/src/main/java/io/dapr/actors/runtime/DaprStateAsyncProvider.java @@ -7,10 +7,8 @@ package io.dapr.actors.runtime; import com.fasterxml.jackson.databind.ObjectMapper; import io.dapr.actors.ActorId; -import io.dapr.client.ObjectSerializer; import io.dapr.config.Properties; import io.dapr.serializer.DaprObjectSerializer; -import io.dapr.serializer.DefaultObjectSerializer; import io.dapr.utils.TypeRef; import reactor.core.publisher.Mono; @@ -28,6 +26,9 @@ class DaprStateAsyncProvider { */ private static final Charset CHARSET = Properties.STRING_CHARSET.get(); + /** + * Marker to identify Json serializers. + */ public static final String JSON_CONTENT_TYPE = "application/json"; /** diff --git a/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java b/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java index caf53d127..dcabd6a82 100644 --- a/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java +++ b/sdk-actors/src/test/java/io/dapr/actors/runtime/DaprStateAsyncProviderTest.java @@ -145,7 +145,7 @@ public class DaprStateAsyncProviderTest { }))) .thenReturn(Mono.empty()); - DaprStateAsyncProvider provider = new DaprStateAsyncProvider(daprClient, new CustomJsonSerializer()); + DaprStateAsyncProvider provider = new DaprStateAsyncProvider(daprClient, SERIALIZER); provider.apply("MyActor", new ActorId("123"), createInsertChange("name", "Jon Doe"), @@ -190,7 +190,7 @@ public class DaprStateAsyncProviderTest { }))) .thenReturn(Mono.empty()); - DaprStateAsyncProvider provider = new DaprStateAsyncProvider(daprClient, SERIALIZER); + DaprStateAsyncProvider provider = new DaprStateAsyncProvider(daprClient, new CustomJsonSerializer()); provider.apply("MyActor", new ActorId("123"), createInsertChange("object", new Customer().setId(1000).setName("Roxane")))