Skip to content

Commit 805ebca

Browse files
mbaechlerchibenwa
authored andcommitted
JAMES-2813 use a staged builder to create serializers
1 parent 1af080d commit 805ebca

File tree

48 files changed

+262
-224
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+262
-224
lines changed

backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/migration/MigrationTaskSerializationTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ class MigrationTaskSerializationTest {
4343
private final CassandraSchemaVersionDAO cassandraSchemaVersionDAO = mock(CassandraSchemaVersionDAO.class);
4444
private final CassandraSchemaTransitions transitions = mock(CassandraSchemaTransitions.class);
4545
private final MigrationTask.Factory factory = target -> new MigrationTask(cassandraSchemaVersionDAO, transitions, target);
46-
private final JsonTaskSerializer taskSerializer = new JsonTaskSerializer(MigrationTaskDTO.module(factory));
47-
private JsonTaskAdditionalInformationSerializer jsonAdditionalInformationSerializer = new JsonTaskAdditionalInformationSerializer(MigrationTaskAdditionalInformationDTO.serializationModule());
46+
private final JsonTaskSerializer taskSerializer = JsonTaskSerializer.of(MigrationTaskDTO.module(factory));
47+
private JsonTaskAdditionalInformationSerializer jsonAdditionalInformationSerializer = JsonTaskAdditionalInformationSerializer.of(MigrationTaskAdditionalInformationDTO.serializationModule());
4848

4949
@Test
5050
void taskShouldBeSerializable() throws JsonProcessingException {

event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/JsonEventSerializer.java

+33-7
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,52 @@
2020
package org.apache.james.eventsourcing.eventstore.cassandra;
2121

2222
import java.io.IOException;
23+
import java.util.Arrays;
24+
import java.util.Collection;
2325
import java.util.Set;
2426

2527
import javax.inject.Inject;
2628

2729
import org.apache.james.eventsourcing.Event;
2830
import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTO;
2931
import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTOModule;
30-
import org.apache.james.json.DTOConverter;
3132
import org.apache.james.json.DTOModule;
3233
import org.apache.james.json.JsonGenericSerializer;
3334

3435
import com.fasterxml.jackson.core.JsonProcessingException;
36+
import com.github.steveash.guavate.Guavate;
3537
import com.google.common.collect.ImmutableSet;
3638

3739
public class JsonEventSerializer {
3840

41+
public static RequireNestedConfiguration forModules(Set<? extends EventDTOModule<?, ?>> modules) {
42+
return nestedTypesModules -> {
43+
ImmutableSet<EventDTOModule<?, ?>> dtoModules = ImmutableSet.copyOf(modules);
44+
return new JsonEventSerializer(dtoModules, ImmutableSet.copyOf(nestedTypesModules));
45+
};
46+
}
47+
48+
@SafeVarargs
49+
public static RequireNestedConfiguration forModules(EventDTOModule<?, ?>... modules) {
50+
return forModules(ImmutableSet.copyOf(modules));
51+
}
52+
53+
public interface RequireNestedConfiguration {
54+
JsonEventSerializer withNestedTypeModules(Set<DTOModule<?, ?>> modules);
55+
56+
default JsonEventSerializer withNestedTypeModules(DTOModule<?, ?>... modules) {
57+
return withNestedTypeModules(ImmutableSet.copyOf(modules));
58+
}
59+
60+
default JsonEventSerializer withNestedTypeModules(Set<DTOModule<?, ?>>... modules) {
61+
return withNestedTypeModules(Arrays.stream(modules).flatMap(Collection::stream).collect(Guavate.toImmutableSet()));
62+
}
63+
64+
default JsonEventSerializer withoutNestedType() {
65+
return withNestedTypeModules(ImmutableSet.of());
66+
}
67+
}
68+
3969
public static class InvalidEventException extends RuntimeException {
4070
public InvalidEventException(JsonGenericSerializer.InvalidTypeException original) {
4171
super(original);
@@ -51,14 +81,10 @@ public UnknownEventException(JsonGenericSerializer.UnknownTypeException original
5181
private JsonGenericSerializer<Event, EventDTO> jsonGenericSerializer;
5282

5383
@Inject
54-
public JsonEventSerializer(DTOConverter<Event, EventDTO> converter, Set<EventDTOModule<?, ?>> modules, Set<DTOModule<?, ?>> nestedTypesModules) {
55-
jsonGenericSerializer = new JsonGenericSerializer<>(modules, nestedTypesModules, converter);
84+
private JsonEventSerializer(Set<EventDTOModule<?, ?>> modules, Set<DTOModule<?, ?>> nestedTypesModules) {
85+
jsonGenericSerializer = JsonGenericSerializer.forModules(modules).withNestedTypeModules(nestedTypesModules);
5686
}
5787

58-
public JsonEventSerializer(EventDTOModule<?, ?>... modules) {
59-
this(new DTOConverter<>(ImmutableSet.copyOf(modules)), ImmutableSet.copyOf(modules), ImmutableSet.of());
60-
}
61-
6288
public String serialize(Event event) throws JsonProcessingException {
6389
try {
6490
return jsonGenericSerializer.serialize(event);

event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/CassandraEventSourcingSystemTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@
2525

2626
public class CassandraEventSourcingSystemTest implements EventSourcingSystemTest {
2727
@RegisterExtension
28-
static CassandraEventStoreExtension eventStoreExtension = new CassandraEventStoreExtension(TestEventDTOModules.TEST_TYPE);
28+
static CassandraEventStoreExtension eventStoreExtension = new CassandraEventStoreExtension(JsonEventSerializer.forModules(TestEventDTOModules.TEST_TYPE).withoutNestedType());
2929
}

event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/CassandraEventStoreExtension.java

+6-14
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,8 @@
1919

2020
package org.apache.james.eventsourcing.eventstore.cassandra;
2121

22-
import java.util.Set;
23-
2422
import org.apache.james.backends.cassandra.CassandraClusterExtension;
2523
import org.apache.james.eventsourcing.eventstore.EventStore;
26-
import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTOModule;
27-
import org.apache.james.json.DTOConverter;
2824
import org.junit.jupiter.api.extension.AfterAllCallback;
2925
import org.junit.jupiter.api.extension.AfterEachCallback;
3026
import org.junit.jupiter.api.extension.BeforeAllCallback;
@@ -34,21 +30,19 @@
3430
import org.junit.jupiter.api.extension.ParameterResolutionException;
3531
import org.junit.jupiter.api.extension.ParameterResolver;
3632

37-
import com.google.common.collect.ImmutableSet;
38-
3933
public class CassandraEventStoreExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback, ParameterResolver {
4034

41-
private final Set<EventDTOModule<?, ?>> modules;
4235
private CassandraClusterExtension cassandra;
36+
private final JsonEventSerializer eventSerializer;
4337
private EventStoreDao eventStoreDao;
4438

45-
public CassandraEventStoreExtension(@SuppressWarnings("rawtypes") EventDTOModule... modules) {
46-
this(new CassandraClusterExtension(CassandraEventStoreModule.MODULE), ImmutableSet.copyOf(modules));
39+
public CassandraEventStoreExtension(JsonEventSerializer eventSerializer) {
40+
this(new CassandraClusterExtension(CassandraEventStoreModule.MODULE), eventSerializer);
4741
}
4842

49-
public CassandraEventStoreExtension(CassandraClusterExtension cassandra, Set<EventDTOModule<?, ?>> module) {
43+
public CassandraEventStoreExtension(CassandraClusterExtension cassandra, JsonEventSerializer eventSerializer) {
5044
this.cassandra = cassandra;
51-
this.modules = module;
45+
this.eventSerializer = eventSerializer;
5246
}
5347

5448
@Override
@@ -63,9 +57,7 @@ public void afterAll(ExtensionContext context) {
6357

6458
@Override
6559
public void beforeEach(ExtensionContext context) {
66-
JsonEventSerializer jsonEventSerializer = new JsonEventSerializer(modules.toArray(new EventDTOModule[0]));
67-
68-
eventStoreDao = new EventStoreDao(cassandra.getCassandraCluster().getConf(), jsonEventSerializer);
60+
eventStoreDao = new EventStoreDao(cassandra.getCassandraCluster().getConf(), eventSerializer);
6961
}
7062

7163
@Override

event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/CassandraEventStoreTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@
2525

2626
class CassandraEventStoreTest implements EventStoreTest {
2727
@RegisterExtension
28-
static CassandraEventStoreExtension eventStoreExtension = new CassandraEventStoreExtension(TestEventDTOModules.TEST_TYPE);
28+
static CassandraEventStoreExtension eventStoreExtension = new CassandraEventStoreExtension(JsonEventSerializer.forModules(TestEventDTOModules.TEST_TYPE).withoutNestedType());
2929
}

event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/JsonEventSerializerTest.java

+16-17
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import org.apache.james.eventsourcing.TestEvent;
2929
import org.apache.james.eventsourcing.eventstore.cassandra.dto.OtherEvent;
3030
import org.apache.james.eventsourcing.eventstore.cassandra.dto.TestEventDTOModules;
31-
import org.apache.james.json.DTOModule;
3231
import org.junit.jupiter.api.Test;
3332

3433
class JsonEventSerializerTest {
@@ -45,23 +44,23 @@ class JsonEventSerializerTest {
4544

4645
@Test
4746
void shouldDeserializeKnownEvent() throws Exception {
48-
assertThat(new JsonEventSerializer(TestEventDTOModules.TEST_TYPE)
47+
assertThat(JsonEventSerializer.forModules(TestEventDTOModules.TEST_TYPE).withoutNestedType()
4948
.deserialize(TEST_EVENT_JSON))
5049
.isEqualTo(TEST_EVENT);
5150
}
5251

5352
@Test
5453
void shouldThrowWhenDeserializeUnknownEvent() {
55-
assertThatThrownBy(() -> new JsonEventSerializer()
54+
assertThatThrownBy(() -> JsonEventSerializer.forModules().withoutNestedType()
5655
.deserialize(TEST_EVENT_JSON))
5756
.isInstanceOf(JsonEventSerializer.UnknownEventException.class);
5857
}
5958

6059
@Test
6160
void serializeShouldHandleAllKnownEvents() throws Exception {
62-
JsonEventSerializer jsonEventSerializer = new JsonEventSerializer(
63-
TestEventDTOModules.TEST_TYPE,
64-
TestEventDTOModules.OTHER_TEST_TYPE);
61+
JsonEventSerializer jsonEventSerializer = JsonEventSerializer
62+
.forModules(TestEventDTOModules.TEST_TYPE, TestEventDTOModules.OTHER_TEST_TYPE)
63+
.withoutNestedType();
6564

6665
assertThatJson(
6766
jsonEventSerializer.serialize(OTHER_EVENT))
@@ -74,9 +73,9 @@ void serializeShouldHandleAllKnownEvents() throws Exception {
7473

7574
@Test
7675
void deserializeShouldHandleAllKnownEvents() throws Exception {
77-
JsonEventSerializer jsonEventSerializer = new JsonEventSerializer(
78-
TestEventDTOModules.TEST_TYPE,
79-
TestEventDTOModules.OTHER_TEST_TYPE);
76+
JsonEventSerializer jsonEventSerializer = JsonEventSerializer
77+
.forModules(TestEventDTOModules.TEST_TYPE, TestEventDTOModules.OTHER_TEST_TYPE)
78+
.withoutNestedType();
8079

8180
assertThatJson(
8281
jsonEventSerializer.deserialize(OTHER_EVENT_JSON))
@@ -90,32 +89,32 @@ void deserializeShouldHandleAllKnownEvents() throws Exception {
9089

9190
@Test
9291
void deserializeShouldThrowWhenEventWithDuplicatedTypes() {
93-
assertThatThrownBy(() -> new JsonEventSerializer(
94-
TestEventDTOModules.TEST_TYPE,
95-
TestEventDTOModules.OTHER_TEST_TYPE)
92+
assertThatThrownBy(() -> JsonEventSerializer
93+
.forModules(TestEventDTOModules.TEST_TYPE, TestEventDTOModules.OTHER_TEST_TYPE)
94+
.withoutNestedType()
9695
.deserialize(DUPLICATE_TYPE_EVENT_JSON))
9796
.isInstanceOf(JsonEventSerializer.InvalidEventException.class);
9897
}
9998

10099
@Test
101100
void deserializeShouldThrowWhenEventWithMissingType() {
102-
assertThatThrownBy(() -> new JsonEventSerializer(
103-
TestEventDTOModules.TEST_TYPE,
104-
TestEventDTOModules.OTHER_TEST_TYPE)
101+
assertThatThrownBy(() -> JsonEventSerializer
102+
.forModules(TestEventDTOModules.TEST_TYPE, TestEventDTOModules.OTHER_TEST_TYPE)
103+
.withoutNestedType()
105104
.deserialize(MISSING_TYPE_EVENT_JSON))
106105
.isInstanceOf(JsonEventSerializer.InvalidEventException.class);
107106
}
108107

109108
@Test
110109
void shouldSerializeKnownEvent() throws Exception {
111-
assertThatJson(new JsonEventSerializer(TestEventDTOModules.TEST_TYPE)
110+
assertThatJson(JsonEventSerializer.forModules(TestEventDTOModules.TEST_TYPE).withoutNestedType()
112111
.serialize(TEST_EVENT))
113112
.isEqualTo(TEST_EVENT_JSON);
114113
}
115114

116115
@Test
117116
void shouldThrowWhenSerializeUnknownEvent() {
118-
assertThatThrownBy(() -> new JsonEventSerializer()
117+
assertThatThrownBy(() -> JsonEventSerializer.forModules().withoutNestedType()
119118
.serialize(TEST_EVENT))
120119
.isInstanceOf(JsonEventSerializer.UnknownEventException.class);
121120
}

json/src/main/java/org/apache/james/json/JsonGenericSerializer.java

+35-8
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
package org.apache.james.json;
2121

2222
import java.io.IOException;
23+
import java.util.Arrays;
24+
import java.util.Collection;
2325
import java.util.Set;
2426

2527
import com.fasterxml.jackson.annotation.JsonInclude;
@@ -34,11 +36,40 @@
3436
import com.fasterxml.jackson.datatype.guava.GuavaModule;
3537
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
3638
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
39+
import com.github.steveash.guavate.Guavate;
3740
import com.google.common.collect.ImmutableSet;
3841
import com.google.common.collect.Sets;
3942

4043
public class JsonGenericSerializer<T, U extends DTO> {
4144

45+
public static <T, U extends DTO> RequireNestedConfiguration<T, U> forModules(Set<? extends DTOModule<? extends T, ? extends U>> modules) {
46+
return nestedTypesModules -> {
47+
ImmutableSet<DTOModule<? extends T, ? extends U>> dtoModules = ImmutableSet.copyOf(modules);
48+
return new JsonGenericSerializer<>(dtoModules, ImmutableSet.copyOf(nestedTypesModules), new DTOConverter<>(dtoModules));
49+
};
50+
}
51+
52+
@SafeVarargs
53+
public static <T, U extends DTO> RequireNestedConfiguration<T, U> forModules(DTOModule<? extends T, ? extends U>... modules) {
54+
return forModules(ImmutableSet.copyOf(modules));
55+
}
56+
57+
public interface RequireNestedConfiguration<T, U extends DTO> {
58+
JsonGenericSerializer<T, U> withNestedTypeModules(Set<DTOModule<?, ?>> modules);
59+
60+
default JsonGenericSerializer<T, U> withNestedTypeModules(DTOModule<?, ?>... modules) {
61+
return withNestedTypeModules(ImmutableSet.copyOf(modules));
62+
}
63+
64+
default JsonGenericSerializer<T, U> withNestedTypeModules(Set<DTOModule<?, ?>>... modules) {
65+
return withNestedTypeModules(Arrays.stream(modules).flatMap(Collection::stream).collect(Guavate.toImmutableSet()));
66+
}
67+
68+
default JsonGenericSerializer<T, U> withoutNestedType() {
69+
return withNestedTypeModules(ImmutableSet.of());
70+
}
71+
}
72+
4273
public static class InvalidTypeException extends RuntimeException {
4374
public InvalidTypeException(String message) {
4475
super(message);
@@ -58,12 +89,7 @@ public UnknownTypeException(String message) {
5889
private final ObjectMapper objectMapper;
5990
private final DTOConverter<T, U> dtoConverter;
6091

61-
@SafeVarargs
62-
public static <T, U extends DTO> JsonGenericSerializer<T, U> of(DTOModule<T, U>... modules) {
63-
return new JsonGenericSerializer<>(ImmutableSet.copyOf(modules), ImmutableSet.of(), DTOConverter.of(modules));
64-
}
65-
66-
public JsonGenericSerializer(Set<? extends DTOModule<? extends T, ? extends U>> modules, Set<? extends DTOModule<?, ?>> nestedTypesModules, DTOConverter<T, U> converter) {
92+
private JsonGenericSerializer(Set<? extends DTOModule<? extends T, ? extends U>> modules, Set<? extends DTOModule<?, ?>> nestedTypesModules, DTOConverter<T, U> converter) {
6793
this.dtoConverter = converter;
6894
this.objectMapper = buildObjectMapper(Sets.union(modules, nestedTypesModules));
6995
}
@@ -76,9 +102,10 @@ private ObjectMapper buildObjectMapper(Set<? extends DTOModule<?, ?>> modules) {
76102
.setSerializationInclusion(JsonInclude.Include.NON_ABSENT)
77103
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
78104
.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
79-
modules.stream()
105+
NamedType[] namedTypes = modules.stream()
80106
.map(module -> new NamedType(module.getDTOClass(), module.getDomainObjectType()))
81-
.forEach(objectMapper::registerSubtypes);
107+
.toArray(NamedType[]::new);
108+
objectMapper.registerSubtypes(namedTypes);
82109
return objectMapper;
83110
}
84111

json/src/test/java/org/apache/DTOConverterTest.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,16 @@
4343
class DTOConverterTest {
4444
private static final Optional<NestedType> NO_CHILD = Optional.empty();
4545
private static final Optional<DTO> NO_CHILD_DTO = Optional.empty();
46-
private static final FirstDomainObject FIRST = new FirstDomainObject(Optional.of(1L), ZonedDateTime.parse("2016-04-03T02:01+07:00[Asia/Vientiane]"), "first payload", NO_CHILD);
47-
private static final FirstDTO FIRST_DTO = new FirstDTO("first", Optional.of(1L), "2016-04-03T02:01+07:00[Asia/Vientiane]", "first payload", NO_CHILD_DTO);
48-
private static final SecondDomainObject SECOND = new SecondDomainObject(UUID.fromString("4a2c853f-7ffc-4ce3-9410-a47e85b3b741"), "second payload", NO_CHILD);
49-
private static final SecondDTO SECOND_DTO = new SecondDTO("second", "4a2c853f-7ffc-4ce3-9410-a47e85b3b741", "second payload", NO_CHILD_DTO);
46+
private static final BaseType FIRST = new FirstDomainObject(Optional.of(1L), ZonedDateTime.parse("2016-04-03T02:01+07:00[Asia/Vientiane]"), "first payload", NO_CHILD);
47+
private static final DTO FIRST_DTO = new FirstDTO("first", Optional.of(1L), "2016-04-03T02:01+07:00[Asia/Vientiane]", "first payload", NO_CHILD_DTO);
48+
private static final BaseType SECOND = new SecondDomainObject(UUID.fromString("4a2c853f-7ffc-4ce3-9410-a47e85b3b741"), "second payload", NO_CHILD);
49+
private static final DTO SECOND_DTO = new SecondDTO("second", "4a2c853f-7ffc-4ce3-9410-a47e85b3b741", "second payload", NO_CHILD_DTO);
5050

5151
@SuppressWarnings("unchecked")
5252
@Test
5353
void shouldConvertFromKnownDTO() throws Exception {
54-
assertThat(DTOConverter.of(TestModules.FIRST_TYPE)
54+
assertThat(DTOConverter
55+
.<BaseType, DTO>of(TestModules.FIRST_TYPE)
5556
.convert(FIRST_DTO))
5657
.contains(FIRST);
5758
}
@@ -105,7 +106,7 @@ private static Stream<Arguments> allKnownTypes() {
105106
@SuppressWarnings("unchecked")
106107
@Test
107108
void shouldConvertFromKnownDomainObject() throws Exception {
108-
assertThat(DTOConverter.of(TestModules.FIRST_TYPE)
109+
assertThat(DTOConverter.<BaseType, DTO>of(TestModules.FIRST_TYPE)
109110
.convert(FIRST))
110111
.hasValueSatisfying(result -> assertThat(result).isInstanceOf(FirstDTO.class).isEqualToComparingFieldByField(FIRST_DTO));
111112
}

0 commit comments

Comments
 (0)