You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2019/11/20 07:32:03 UTC
[james-project] 20/41: JAMES-2813 Split JsonGenericSerializer
between conversion and serialization
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 27f2845344e1a97c63215d512aa3e17110f3083b
Author: Matthieu Baechler <ma...@apache.org>
AuthorDate: Mon Oct 21 10:14:42 2019 +0200
JAMES-2813 Split JsonGenericSerializer between conversion and serialization
---
.../eventstore/cassandra/JsonEventSerializer.java | 3 +-
.../java/org/apache/james/json/DTOConverter.java | 65 ++++++++++++
.../apache/james/json/JsonGenericSerializer.java | 60 +++--------
.../src/test/java/org/apache/DTOConverterTest.java | 115 +++++++++++++++++++++
.../JsonTaskAdditionalInformationSerializer.java | 3 +-
.../james/server/task/json/JsonTaskSerializer.java | 3 +-
6 files changed, 202 insertions(+), 47 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 52b0d3a..0bc17a1 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
@@ -50,7 +50,8 @@ public class JsonEventSerializer {
@Inject
public JsonEventSerializer(Set<EventDTOModule<?, ?>> modules) {
- jsonGenericSerializer = new JsonGenericSerializer(modules);
+ //FIXME
+ jsonGenericSerializer = new JsonGenericSerializer(modules, null);
}
public JsonEventSerializer(EventDTOModule<?, ?>... modules) {
diff --git a/json/src/main/java/org/apache/james/json/DTOConverter.java b/json/src/main/java/org/apache/james/json/DTOConverter.java
new file mode 100644
index 0000000..1fe27f3
--- /dev/null
+++ b/json/src/main/java/org/apache/james/json/DTOConverter.java
@@ -0,0 +1,65 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.json;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+
+import com.github.steveash.guavate.Guavate;
+import com.google.common.collect.ImmutableSet;
+
+public class DTOConverter<T, U extends DTO> {
+
+ private final Map<String, DTOModule<T, U>> typeToModule;
+ private final Map<Class<? extends T>, DTOModule<T, U>> domainClassToModule;
+
+ @SafeVarargs
+ public static <T, U extends DTO> DTOConverter<T, U> of(DTOModule<T, U>... modules) {
+ return new DTOConverter<>(ImmutableSet.copyOf(modules));
+ }
+
+ public DTOConverter(Set<DTOModule<T, U>> modules) {
+ typeToModule = modules.stream()
+ .collect(Guavate.toImmutableMap(
+ DTOModule::getDomainObjectType,
+ Function.identity()));
+
+ domainClassToModule = modules.stream()
+ .collect(Guavate.toImmutableMap(
+ DTOModule::getDomainObjectClass,
+ Function.identity()));
+ }
+
+ public Optional<U> convert(T domainObject) {
+ return Optional
+ .ofNullable(domainClassToModule.get(domainObject.getClass()))
+ .map(module -> module.toDTO(domainObject));
+ }
+
+ public Optional<T> convert(U dto) {
+ String type = dto.getType();
+ return Optional
+ .ofNullable(typeToModule.get(type))
+ .map(DTOModule::getToDomainObjectConverter)
+ .map(convert -> convert.convert(dto));
+ }
+}
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 a1ed925..ceb3066 100644
--- a/json/src/main/java/org/apache/james/json/JsonGenericSerializer.java
+++ b/json/src/main/java/org/apache/james/json/JsonGenericSerializer.java
@@ -20,10 +20,7 @@
package org.apache.james.json;
import java.io.IOException;
-import java.util.Map;
-import java.util.Optional;
import java.util.Set;
-import java.util.function.Function;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -37,40 +34,10 @@ import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-import com.github.steveash.guavate.Guavate;
import com.google.common.collect.ImmutableSet;
public class JsonGenericSerializer<T, U extends DTO> {
- private static class DTOConverter<T, U extends DTO> {
-
- private final Map<String, DTOModule<T, U>> typeToModule;
- private final Map<Class<? extends T>, DTOModule<T, U>> domainClassToModule;
-
- public DTOConverter(Set<DTOModule<T, U>> modules) {
- typeToModule = modules.stream()
- .collect(Guavate.toImmutableMap(
- DTOModule::getDomainObjectType,
- Function.identity()));
-
- domainClassToModule = modules.stream()
- .collect(Guavate.toImmutableMap(
- DTOModule::getDomainObjectClass,
- Function.identity()));
- }
-
- public Optional<U> convert(T domainObject) {
- return Optional.ofNullable(domainClassToModule.get(domainObject.getClass()))
- .map(module -> module.toDTO(domainObject));
- }
-
- public Optional<T> convert(U dto) {
- String type = dto.getType();
- return Optional.ofNullable(typeToModule.get(type))
- .map(module -> module.getToDomainObjectConverter().convert(dto));
- }
- }
-
public static class InvalidTypeException extends RuntimeException {
public InvalidTypeException(String message) {
super(message);
@@ -92,21 +59,26 @@ public class JsonGenericSerializer<T, U extends DTO> {
@SafeVarargs
public static <T, U extends DTO> JsonGenericSerializer<T, U> of(DTOModule<T, U>... modules) {
- return new JsonGenericSerializer<>(ImmutableSet.copyOf(modules));
+ return new JsonGenericSerializer<>(ImmutableSet.copyOf(modules), DTOConverter.of(modules));
+ }
+
+ public JsonGenericSerializer(Set<DTOModule<T, U>> modules, DTOConverter<T, U> converter) {
+ this.dtoConverter = converter;
+ this.objectMapper = buildObjectMapper(modules);
}
- public JsonGenericSerializer(Set<DTOModule<T, U>> modules) {
- objectMapper = new ObjectMapper();
- objectMapper.registerModule(new Jdk8Module());
- objectMapper.registerModule(new JavaTimeModule());
- objectMapper.registerModule(new GuavaModule());
- objectMapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT);
- objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
- objectMapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
+ private ObjectMapper buildObjectMapper(Set<DTOModule<T, U>> modules) {
+ ObjectMapper objectMapper = new ObjectMapper()
+ .registerModule(new Jdk8Module())
+ .registerModule(new JavaTimeModule())
+ .registerModule(new GuavaModule())
+ .setSerializationInclusion(JsonInclude.Include.NON_ABSENT)
+ .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
+ .enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
modules.stream()
.map(module -> new NamedType(module.getDTOClass(), module.getDomainObjectType()))
.forEach(objectMapper::registerSubtypes);
- dtoConverter = new DTOConverter<>(modules);
+ return objectMapper;
}
public String serialize(T domainObject) throws JsonProcessingException {
@@ -122,7 +94,7 @@ public class JsonGenericSerializer<T, U extends DTO> {
.orElseThrow(() -> new UnknownTypeException("unknown type " + dto.getType()));
}
- public U jsonToDTO(String value) throws IOException {
+ private U jsonToDTO(String value) throws IOException {
try {
JsonNode jsonTree = detectDuplicateProperty(value);
return parseAsPolymorphicDTO(jsonTree);
diff --git a/json/src/test/java/org/apache/DTOConverterTest.java b/json/src/test/java/org/apache/DTOConverterTest.java
new file mode 100644
index 0000000..3987dbd
--- /dev/null
+++ b/json/src/test/java/org/apache/DTOConverterTest.java
@@ -0,0 +1,115 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.time.ZonedDateTime;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.stream.Stream;
+
+import org.apache.dto.BaseType;
+import org.apache.dto.FirstDTO;
+import org.apache.dto.FirstDomainObject;
+import org.apache.dto.SecondDTO;
+import org.apache.dto.SecondDomainObject;
+import org.apache.dto.TestModules;
+import org.apache.james.json.DTO;
+import org.apache.james.json.DTOConverter;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+class DTOConverterTest {
+ 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 FirstDTO FIRST_DTO = new FirstDTO("first", Optional.of(1L), "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 SecondDTO SECOND_DTO = new SecondDTO("second", "4a2c853f-7ffc-4ce3-9410-a47e85b3b741", "second payload");
+
+ @SuppressWarnings("unchecked")
+ @Test
+ void shouldConvertFromKnownDTO() throws Exception {
+ assertThat(DTOConverter.of(TestModules.FIRST_TYPE)
+ .convert(FIRST_DTO))
+ .contains(FIRST);
+ }
+
+ @Test
+ void shouldReturnEmptyWhenConvertingFromUnknownDTO() {
+ assertThat(DTOConverter.of()
+ .convert(FIRST_DTO))
+ .isEmpty();
+ }
+
+ @ParameterizedTest
+ @MethodSource
+ void convertFromDomainObjectShouldHandleAllKnownTypes(BaseType domainObject, DTO dto) throws Exception {
+ @SuppressWarnings("unchecked")
+ DTOConverter<BaseType, DTO> serializer = DTOConverter.of(
+ TestModules.FIRST_TYPE,
+ TestModules.SECOND_TYPE);
+
+ assertThat(serializer.convert(domainObject))
+ .hasValueSatisfying(result -> assertThat(result).isInstanceOf(dto.getClass()).isEqualToComparingFieldByField(dto));
+ }
+
+ private static Stream<Arguments> convertFromDomainObjectShouldHandleAllKnownTypes() {
+ return allKnownTypes();
+ }
+
+ @ParameterizedTest
+ @MethodSource
+ void convertFromDTOShouldHandleAllKnownTypes(BaseType domainObject, DTO dto) throws Exception {
+ @SuppressWarnings("unchecked")
+ DTOConverter<BaseType, DTO> serializer = DTOConverter.of(
+ TestModules.FIRST_TYPE,
+ TestModules.SECOND_TYPE);
+
+ assertThat(serializer.convert(dto))
+ .hasValueSatisfying(result -> assertThat(result).isInstanceOf(domainObject.getClass()).isEqualToComparingFieldByField(domainObject));
+ }
+
+ private static Stream<Arguments> convertFromDTOShouldHandleAllKnownTypes() {
+ return allKnownTypes();
+ }
+
+ private static Stream<Arguments> allKnownTypes() {
+ return Stream.of(
+ Arguments.of(SECOND, SECOND_DTO),
+ Arguments.of(FIRST, FIRST_DTO)
+ );
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ void shouldConvertFromKnownDomainObject() throws Exception {
+ assertThat(DTOConverter.of(TestModules.FIRST_TYPE)
+ .convert(FIRST))
+ .hasValueSatisfying(result -> assertThat(result).isInstanceOf(FirstDTO.class).isEqualToComparingFieldByField(FIRST_DTO));
+ }
+
+ @Test
+ void shouldReturnEmptyWhenConvertUnknownDomainObject() {
+ assertThat(DTOConverter.of().convert(FIRST))
+ .isEmpty();
+ }
+}
diff --git a/server/task/task-json/src/main/java/org/apache/james/server/task/json/JsonTaskAdditionalInformationSerializer.java b/server/task/task-json/src/main/java/org/apache/james/server/task/json/JsonTaskAdditionalInformationSerializer.java
index 751cc17..5d0cc48 100644
--- a/server/task/task-json/src/main/java/org/apache/james/server/task/json/JsonTaskAdditionalInformationSerializer.java
+++ b/server/task/task-json/src/main/java/org/apache/james/server/task/json/JsonTaskAdditionalInformationSerializer.java
@@ -49,7 +49,8 @@ public class JsonTaskAdditionalInformationSerializer {
@Inject
public JsonTaskAdditionalInformationSerializer(Set<AdditionalInformationDTOModule<?, ?>> modules) {
- jsonGenericSerializer = new JsonGenericSerializer(modules);
+ //FIXME
+ jsonGenericSerializer = new JsonGenericSerializer(modules, null);
}
public JsonTaskAdditionalInformationSerializer(@SuppressWarnings("rawtypes") AdditionalInformationDTOModule... modules) {
diff --git a/server/task/task-json/src/main/java/org/apache/james/server/task/json/JsonTaskSerializer.java b/server/task/task-json/src/main/java/org/apache/james/server/task/json/JsonTaskSerializer.java
index 9ecd7c4..90ebe54 100644
--- a/server/task/task-json/src/main/java/org/apache/james/server/task/json/JsonTaskSerializer.java
+++ b/server/task/task-json/src/main/java/org/apache/james/server/task/json/JsonTaskSerializer.java
@@ -50,7 +50,8 @@ public class JsonTaskSerializer {
@Inject
public JsonTaskSerializer(Set<TaskDTOModule<?, ?>> modules) {
- jsonGenericSerializer = new JsonGenericSerializer(modules);
+ //FIXME
+ jsonGenericSerializer = new JsonGenericSerializer(modules, null);
}
public JsonTaskSerializer(@SuppressWarnings("rawtypes") TaskDTOModule... modules) {
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org