This is an automated email from the ASF dual-hosted git repository.

rouazana pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit f61d59593f57eb4b9c0834e95071ea67af2adc32
Author: RĂ©mi Kowalski <[email protected]>
AuthorDate: Tue Jul 16 15:12:20 2019 +0200

    JAMES-2813 Handle missing and duplicate types for DTO deserialization
---
 .../eventstore/cassandra/JsonEventSerializer.java  |  8 +++++
 .../cassandra/JsonEventSerializerTest.java         | 22 +++++++++++++
 .../apache/james/json/JsonGenericSerializer.java   | 36 +++++++++++++++++-----
 .../java/org/apache/JsonGenericSerializerTest.java | 20 +++++++++++-
 .../james/server/task/json/JsonTaskSerializer.java |  9 ++++++
 .../server/task/json/TaskDeserializerTest.java     |  4 +--
 6 files changed, 89 insertions(+), 10 deletions(-)

diff --git 
a/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/JsonEventSerializer.java
 
b/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/JsonEventSerializer.java
index 4303ce5..943abc4 100644
--- 
a/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/JsonEventSerializer.java
+++ 
b/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/JsonEventSerializer.java
@@ -34,6 +34,12 @@ import com.google.common.collect.ImmutableSet;
 
 public class JsonEventSerializer {
 
+    public static class InvalidEventException extends RuntimeException {
+        public 
InvalidEventException(JsonGenericSerializer.InvalidTypeException original) {
+            super(original);
+        }
+    }
+
     public static class UnknownEventException extends RuntimeException {
         public 
UnknownEventException(JsonGenericSerializer.UnknownTypeException original) {
             super(original);
@@ -64,6 +70,8 @@ public class JsonEventSerializer {
             return jsonGenericSerializer.deserialize(value);
         } catch (JsonGenericSerializer.UnknownTypeException e) {
             throw new UnknownEventException(e);
+        } catch (JsonGenericSerializer.InvalidTypeException e) {
+            throw new InvalidEventException(e);
         }
     }
 
diff --git 
a/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/JsonEventSerializerTest.java
 
b/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/JsonEventSerializerTest.java
index bfa669f..d042a44 100644
--- 
a/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/JsonEventSerializerTest.java
+++ 
b/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/JsonEventSerializerTest.java
@@ -39,6 +39,8 @@ class JsonEventSerializerTest {
 
     public static final String TEST_EVENT_JSON = 
"{\"type\":\"TestType\",\"data\":\"first\",\"eventId\":0,\"aggregate\":1}";
     public static final String OTHER_EVENT_JSON = 
"{\"type\":\"other-type\",\"data\":1,\"eventId\":0,\"aggregate\":1}";
+    public static final String MISSING_TYPE_EVENT_JSON = 
"{\"data\":1,\"eventId\":0,\"aggregate\":1}";
+    public static final String DUPLICATE_TYPE_EVENT_JSON = 
"{\"type\":\"TestType\", 
\"type\":\"other-type\",\"data\":1,\"eventId\":0,\"aggregate\":1}";
 
     @Test
     void shouldDeserializeKnownEvent() throws Exception {
@@ -84,6 +86,25 @@ class JsonEventSerializerTest {
             .isEqualTo(TEST_EVENT);
     }
 
+
+    @Test
+    void deserializeShouldThrowWhenEventWithDuplicatedTypes() {
+        assertThatThrownBy(() -> new JsonEventSerializer(
+                TestEventDTOModules.TEST_TYPE,
+                TestEventDTOModules.OTHER_TEST_TYPE)
+            .deserialize(DUPLICATE_TYPE_EVENT_JSON))
+            .isInstanceOf(JsonEventSerializer.InvalidEventException.class);
+    }
+
+    @Test
+    void deserializeShouldThrowWhenEventWithMissingType() {
+        assertThatThrownBy(() -> new JsonEventSerializer(
+                TestEventDTOModules.TEST_TYPE,
+                TestEventDTOModules.OTHER_TEST_TYPE)
+            .deserialize(MISSING_TYPE_EVENT_JSON))
+            .isInstanceOf(JsonEventSerializer.InvalidEventException.class);
+    }
+
     @Test
     void shouldSerializeKnownEvent() throws Exception {
         assertThatJson(new JsonEventSerializer(TestEventDTOModules.TEST_TYPE)
@@ -98,4 +119,5 @@ class JsonEventSerializerTest {
             .isInstanceOf(JsonEventSerializer.UnknownEventException.class);
     }
 
+
 }
\ No newline at end of file
diff --git 
a/json/src/main/java/org/apache/james/json/JsonGenericSerializer.java 
b/json/src/main/java/org/apache/james/json/JsonGenericSerializer.java
index cd8283d..6934320 100644
--- a/json/src/main/java/org/apache/james/json/JsonGenericSerializer.java
+++ b/json/src/main/java/org/apache/james/json/JsonGenericSerializer.java
@@ -27,8 +27,10 @@ import java.util.function.Function;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
 import com.fasterxml.jackson.datatype.guava.GuavaModule;
 import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
 import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
@@ -36,6 +38,17 @@ import com.github.steveash.guavate.Guavate;
 import com.google.common.collect.ImmutableSet;
 
 public class JsonGenericSerializer<T, U extends DTO<T>> {
+
+    public static class InvalidTypeException extends RuntimeException {
+        public InvalidTypeException(String message) {
+            super(message);
+        }
+
+        public InvalidTypeException(String message, MismatchedInputException 
exception) {
+            super(message, exception);
+        }
+    }
+
     public static class UnknownTypeException extends RuntimeException {
         public UnknownTypeException(String message) {
             super(message);
@@ -57,7 +70,7 @@ public class JsonGenericSerializer<T, U extends DTO<T>> {
         objectMapper.registerModule(new JavaTimeModule());
         objectMapper.registerModule(new GuavaModule());
         objectMapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT);
-
+        
objectMapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
         typeToModule = modules.stream()
             .collect(Guavate.toImmutableMap(
                 DTOModule::getDomainObjectType,
@@ -77,14 +90,22 @@ public class JsonGenericSerializer<T, U extends DTO<T>> {
     }
 
     public T deserialize(String value) throws IOException {
-        JsonNode jsonNode = objectMapper.readTree(value);
+        try {
+            JsonNode jsonNode = objectMapper.readTree(value);
+
+            JsonNode typeNode = jsonNode.path("type");
 
-        String type = jsonNode.path("type").asText();
+            if (typeNode.isMissingNode()) {
+                throw new InvalidTypeException("No \"type\" property found in 
the json document");
+            }
 
-        U dto = objectMapper.readValue(
-            objectMapper.treeAsTokens(jsonNode),
-            retrieveDTOClass(type));
-        return dto.toDomainObject();
+            U dto = objectMapper.readValue(
+                objectMapper.treeAsTokens(jsonNode),
+                retrieveDTOClass(typeNode.asText()));
+            return dto.toDomainObject();
+        } catch (MismatchedInputException e) {
+            throw new InvalidTypeException("Duplicate \"type\" properties 
found in the json document", e);
+        }
     }
 
     private Class<? extends U> retrieveDTOClass(String type) {
@@ -93,4 +114,5 @@ public class JsonGenericSerializer<T, U extends DTO<T>> {
             .orElseThrow(() -> new UnknownTypeException("unknown type " + 
type));
     }
 
+
 }
diff --git a/json/src/test/java/org/apache/JsonGenericSerializerTest.java 
b/json/src/test/java/org/apache/JsonGenericSerializerTest.java
index c69a400..c450e68 100644
--- a/json/src/test/java/org/apache/JsonGenericSerializerTest.java
+++ b/json/src/test/java/org/apache/JsonGenericSerializerTest.java
@@ -43,6 +43,8 @@ class JsonGenericSerializerTest {
     private static final FirstDomainObject FIRST = new 
FirstDomainObject(Optional.of(1L), 
ZonedDateTime.parse("2016-04-03T02:01+07:00[Asia/Vientiane]"), "first payload");
     private static final SecondDomainObject SECOND = new 
SecondDomainObject(UUID.fromString("4a2c853f-7ffc-4ce3-9410-a47e85b3b741"), 
"second payload");
 
+    private static final String MISSING_TYPE_JSON = 
"{\"id\":1,\"time\":\"2016-04-03T02:01+07:00[Asia/Vientiane]\",\"payload\":\"first
 payload\"}";
+    private static final String DUPLICATE_TYPE_JSON = "{\"type\":\"first\", 
\"type\":\"second\", 
\"id\":1,\"time\":\"2016-04-03T02:01+07:00[Asia/Vientiane]\",\"payload\":\"first
 payload\"}";
     private static final String FIRST_JSON = 
"{\"type\":\"first\",\"id\":1,\"time\":\"2016-04-03T02:01+07:00[Asia/Vientiane]\",\"payload\":\"first
 payload\"}";
     private static final String SECOND_JSON = 
"{\"type\":\"second\",\"id\":\"4a2c853f-7ffc-4ce3-9410-a47e85b3b741\",\"payload\":\"second
 payload\"}";
 
@@ -54,6 +56,22 @@ class JsonGenericSerializerTest {
     }
 
     @Test
+    void shouldThrowWhenDeserializeEventWithMissingType() {
+        assertThatThrownBy(() -> 
JsonGenericSerializer.of(TestModules.FIRST_TYPE)
+            .deserialize(MISSING_TYPE_JSON))
+            .isInstanceOf(JsonGenericSerializer.InvalidTypeException.class);
+    }
+
+    @Test
+    void shouldThrowWhenDeserializeEventWithDuplicatedTypes() {
+        assertThatThrownBy(() -> JsonGenericSerializer.of(
+                TestModules.FIRST_TYPE,
+                TestModules.SECOND_TYPE)
+            .deserialize(DUPLICATE_TYPE_JSON))
+            .isInstanceOf(JsonGenericSerializer.InvalidTypeException.class);
+    }
+
+    @Test
     void shouldThrowWhenDeserializeUnknownType() {
         assertThatThrownBy(() -> JsonGenericSerializer.of()
             .deserialize(FIRST_JSON))
@@ -111,4 +129,4 @@ class JsonGenericSerializerTest {
             .isInstanceOf(JsonGenericSerializer.UnknownTypeException.class);
     }
 
-}
\ No newline at end of file
+}
diff --git 
a/server/task-json/src/main/java/org/apache/james/server/task/json/JsonTaskSerializer.java
 
b/server/task-json/src/main/java/org/apache/james/server/task/json/JsonTaskSerializer.java
index a502ce7..21b048e 100644
--- 
a/server/task-json/src/main/java/org/apache/james/server/task/json/JsonTaskSerializer.java
+++ 
b/server/task-json/src/main/java/org/apache/james/server/task/json/JsonTaskSerializer.java
@@ -34,6 +34,12 @@ import com.google.common.collect.ImmutableSet;
 
 public class JsonTaskSerializer {
 
+    public static class InvalidTaskException  extends RuntimeException {
+        public InvalidTaskException(JsonGenericSerializer.InvalidTypeException 
original) {
+            super(original);
+        }
+    }
+
     public static class UnknownTaskException extends RuntimeException {
         public UnknownTaskException(JsonGenericSerializer.UnknownTypeException 
original) {
             super(original);
@@ -64,7 +70,10 @@ public class JsonTaskSerializer {
             return jsonGenericSerializer.deserialize(value);
         } catch (JsonGenericSerializer.UnknownTypeException e) {
             throw new UnknownTaskException(e);
+        } catch (JsonGenericSerializer.InvalidTypeException e) {
+            throw new InvalidTaskException(e);
         }
     }
 
+
 }
diff --git 
a/server/task-json/src/test/java/org/apache/james/server/task/json/TaskDeserializerTest.java
 
b/server/task-json/src/test/java/org/apache/james/server/task/json/TaskDeserializerTest.java
index 13f4062..0cb3d00 100644
--- 
a/server/task-json/src/test/java/org/apache/james/server/task/json/TaskDeserializerTest.java
+++ 
b/server/task-json/src/test/java/org/apache/james/server/task/json/TaskDeserializerTest.java
@@ -72,13 +72,13 @@ class TaskDeserializerTest {
     @Test
     void shouldThrowWhenMissingType() {
         assertThatThrownBy(() -> testee.deserialize(MISSING_TASK_AS_STRING))
-            .isInstanceOf(JsonTaskSerializer.UnknownTaskException.class);
+            .isInstanceOf(JsonTaskSerializer.InvalidTaskException.class);
     }
 
     @Test
     void shouldThrowWhenDuplicateType() {
         assertThatThrownBy(() -> testee.deserialize(TWO_TYPES_TASK_AS_STRING))
-            .isInstanceOf(JsonTaskSerializer.UnknownTaskException.class);
+            .isInstanceOf(JsonTaskSerializer.InvalidTaskException.class);
     }
 
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to