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 2868b35c201256044480b82a765cde57cb63fe47
Author: Matthieu Baechler <[email protected]>
AuthorDate: Mon Jul 15 18:27:43 2019 +0200

    JAMES-2813 Extract JsonEventSerializer to use it out of Events
---
 event-sourcing/event-store-cassandra/pom.xml       |  20 +---
 .../eventstore/cassandra/JsonEventSerializer.java  |  68 +++---------
 .../eventstore/cassandra/dto/EventDTO.java         |   9 +-
 .../eventstore/cassandra/dto/EventDTOModule.java   |  79 ++------------
 .../cassandra/dto/OtherTestEventDTO.java           |   5 +-
 .../eventstore/cassandra/dto/TestEventDTO.java     |   4 +-
 .../cassandra/dto/TestEventDTOModules.java         |  16 +--
 .../event-store-cassandra => json}/pom.xml         |  84 ++++-----------
 json/src/main/java/org/apache/james/json/DTO.java  |   5 +
 .../main/java/org/apache/james/json/DTOModule.java | 114 +++++++++++++++++++++
 .../apache/james/json/JsonGenericSerializer.java   |  60 +++++------
 .../java/org/apache/JsonGenericSerializerTest.java | 114 +++++++++++++++++++++
 json/src/test/java/org/apache/dto/BaseType.java    |   4 +
 .../src/test/java/org/apache/dto/FirstDTO.java     |  50 +++++----
 .../java/org/apache/dto/FirstDomainObject.java     |  54 +++++++---
 .../src/test/java/org/apache/dto/SecondDTO.java    |  46 ++++-----
 .../java/org/apache/dto/SecondDomainObject.java    |  41 ++++++--
 .../src/test/java/org/apache/dto/TestModule.java   |  12 ++-
 .../src/test/java/org/apache/dto/TestModules.java  |  42 ++++----
 .../quota/cassandra/dto/QuotaEventDTOModules.java  |   3 +-
 .../dto/QuotaThresholdChangedEventDTO.java         |   2 +-
 pom.xml                                            |   6 ++
 .../cassandra/DLPConfigurationItemAddedDTO.java    |   2 +-
 .../cassandra/DLPConfigurationItemsRemovedDTO.java |   2 +-
 .../cassandra/DLPConfigurationModules.java         |   6 +-
 .../FilteringRuleSetDefineDTOModules.java          |   3 +-
 .../filtering/FilteringRuleSetDefinedDTO.java      |   5 +-
 .../CassandraMailQueueViewConfigurationModule.java |   3 +-
 .../configuration/ConfigurationChangedDTO.java     |   5 +-
 29 files changed, 491 insertions(+), 373 deletions(-)

diff --git a/event-sourcing/event-store-cassandra/pom.xml 
b/event-sourcing/event-store-cassandra/pom.xml
index 12e4f21..d10d7fa 100644
--- a/event-sourcing/event-store-cassandra/pom.xml
+++ b/event-sourcing/event-store-cassandra/pom.xml
@@ -70,6 +70,10 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-json</artifactId>
+        </dependency>
+        <dependency>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-classic</artifactId>
             <scope>test</scope>
@@ -80,22 +84,6 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.datatype</groupId>
-            <artifactId>jackson-datatype-guava</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.datatype</groupId>
-            <artifactId>jackson-datatype-jdk8</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.datatype</groupId>
-            <artifactId>jackson-datatype-jsr310</artifactId>
-        </dependency>
-        <dependency>
             <groupId>net.javacrumbs.json-unit</groupId>
             <artifactId>json-unit-assertj</artifactId>
             <scope>test</scope>
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 2ab9019..a179a9b 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
@@ -20,57 +20,31 @@
 package org.apache.james.eventsourcing.eventstore.cassandra;
 
 import java.io.IOException;
-import java.util.Map;
-import java.util.Optional;
 import java.util.Set;
-import java.util.function.Function;
 
 import javax.inject.Inject;
 
 import org.apache.james.eventsourcing.Event;
 import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTO;
 import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTOModule;
+import org.apache.james.json.JsonGenericSerializer;
 
-import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-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 JsonEventSerializer {
+
     public static class UnknownEventException extends RuntimeException {
-        public UnknownEventException(String message) {
-            super(message);
+        public 
UnknownEventException(JsonGenericSerializer.UnknownTypeException original) {
+            super(original);
         }
     }
 
-    @SuppressWarnings("rawtypes")
-    private final Map<Class<? extends Event>, EventDTOModule> 
eventClassToModule;
-    @SuppressWarnings("rawtypes")
-    private final Map<String, EventDTOModule> typeToModule;
-    private final ObjectMapper objectMapper;
+    private JsonGenericSerializer<Event, EventDTO<Event>> 
jsonGenericSerializer;
 
     @Inject
     public JsonEventSerializer(@SuppressWarnings("rawtypes") 
Set<EventDTOModule> modules) {
-        objectMapper = new ObjectMapper();
-        objectMapper.registerModule(new Jdk8Module());
-        objectMapper.registerModule(new JavaTimeModule());
-        objectMapper.registerModule(new GuavaModule());
-        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT);
-
-        typeToModule = modules.stream()
-            .collect(Guavate.toImmutableMap(
-                EventDTOModule::getType,
-                Function.identity()));
-
-        eventClassToModule = modules.stream()
-            .collect(Guavate.toImmutableMap(
-                EventDTOModule::getEventClass,
-                Function.identity()));
+        jsonGenericSerializer = new JsonGenericSerializer(modules);
     }
     
     public JsonEventSerializer(@SuppressWarnings("rawtypes") EventDTOModule... 
modules) {
@@ -78,29 +52,19 @@ public class JsonEventSerializer {
     }
 
     public String serialize(Event event) throws JsonProcessingException {
-        @SuppressWarnings("unchecked")
-        EventDTO dto = 
Optional.ofNullable(eventClassToModule.get(event.getClass()))
-            .orElseThrow(() -> new UnknownEventException("unknown event class 
" + event.getClass()))
-            .toDTO(event);
-        return objectMapper.writeValueAsString(dto);
+        try {
+            return jsonGenericSerializer.serialize(event);
+        } catch (JsonGenericSerializer.UnknownTypeException e) {
+            throw new UnknownEventException(e);
+        }
     }
 
     public Event deserialize(String value) throws IOException {
-        JsonNode jsonNode = objectMapper.readTree(value);
-
-        String type = jsonNode.path("type").asText();
-
-        EventDTO dto = objectMapper.readValue(
-            objectMapper.treeAsTokens(jsonNode),
-            retrieveDTOClass(type));
-        return dto.toEvent();
-    }
-
-    @SuppressWarnings("unchecked")
-    public Class<? extends EventDTO> retrieveDTOClass(String type) {
-        return Optional.ofNullable(typeToModule.get(type))
-            .map(EventDTOModule::getDTOClass)
-            .orElseThrow(() -> new UnknownEventException("unknown event type " 
+ type));
+        try {
+            return jsonGenericSerializer.deserialize(value);
+        } catch (JsonGenericSerializer.UnknownTypeException e) {
+            throw new UnknownEventException(e);
+        }
     }
 
 }
diff --git 
a/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/EventDTO.java
 
b/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/EventDTO.java
index 461212a..eeb448a 100644
--- 
a/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/EventDTO.java
+++ 
b/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/EventDTO.java
@@ -20,7 +20,12 @@
 package org.apache.james.eventsourcing.eventstore.cassandra.dto;
 
 import org.apache.james.eventsourcing.Event;
+import org.apache.james.json.DTO;
 
-public interface EventDTO {
-    Event toEvent();
+public interface EventDTO<T extends Event> extends DTO<T> {
+    T toEvent();
+
+    default T toDomainObject() {
+        return toEvent();
+    }
 }
diff --git 
a/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/EventDTOModule.java
 
b/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/EventDTOModule.java
index ba29e91..f68d13a 100644
--- 
a/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/EventDTOModule.java
+++ 
b/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/EventDTOModule.java
@@ -20,81 +20,20 @@
 package org.apache.james.eventsourcing.eventstore.cassandra.dto;
 
 import org.apache.james.eventsourcing.Event;
+import org.apache.james.json.DTOModule;
 
-public class EventDTOModule<T extends Event, U extends EventDTO> {
+public class EventDTOModule<T extends Event, U extends EventDTO<T>> extends 
DTOModule<T, U> {
 
-    public interface EventDTOConverter<T extends Event, U extends EventDTO> {
-        U convert(T event, String typeName);
+    public static <EventTypeT extends Event> DTOModule.Builder<EventTypeT> 
forEvent(Class<EventTypeT> eventType) {
+        return new DTOModule.Builder<>(eventType);
     }
 
-    public static <U extends Event> Builder<U> forEvent(Class<U> eventType) {
-        return new Builder<>(eventType);
+    public EventDTOModule(DTOConverter<T, U> converter, Class<T> 
domainObjectType, Class<U> dtoType, String typeName) {
+        super(converter, domainObjectType, dtoType, typeName);
     }
 
-    public static class Builder<T extends Event> {
-
-        private final Class<T> eventType;
-
-        private Builder(Class<T> eventType) {
-            this.eventType = eventType;
-        }
-
-        public <U extends EventDTO> RequireConversionFunctionBuilder<U> 
convertToDTO(Class<U> dtoType) {
-            return new RequireConversionFunctionBuilder<>(dtoType);
-        }
-
-        public class RequireConversionFunctionBuilder<U extends EventDTO> {
-
-            private final Class<U> dtoType;
-
-            private RequireConversionFunctionBuilder(Class<U> dtoType) {
-                this.dtoType = dtoType;
-            }
-
-            public RequireTypeNameBuilder convertWith(EventDTOConverter<T, U> 
converter) {
-                return new RequireTypeNameBuilder(converter);
-            }
-
-            public class RequireTypeNameBuilder {
-                private final EventDTOConverter<T, U> converter;
-
-                private RequireTypeNameBuilder(EventDTOConverter<T, U> 
converter) {
-                    this.converter = converter;
-                }
-
-                public EventDTOModule<T, U> typeName(String typeName) {
-                    return new EventDTOModule<>(converter, eventType, dtoType, 
typeName);
-                }
-            }
-        }
-
-    }
-
-    private final EventDTOConverter<T, U> converter;
-    private final Class<T> eventType;
-    private final Class<U> dtoType;
-    private final String typeName;
-
-    private EventDTOModule(EventDTOConverter<T, U> converter, Class<T> 
eventType, Class<U> dtoType, String typeName) {
-        this.converter = converter;
-        this.eventType = eventType;
-        this.dtoType = dtoType;
-        this.typeName = typeName;
-    }
-
-    public String getType() {
-        return typeName;
-    }
-
-    public Class<U> getDTOClass() {
-        return dtoType;
-    }
-
-    public Class<T> getEventClass() {
-        return eventType;
-    }
-
-    public EventDTO toDTO(T event) {
-        return converter.convert(event, typeName);
+    @Override
+    public U toDTO(T domainObject) {
+        return super.toDTO(domainObject);
     }
 }
diff --git 
a/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/OtherTestEventDTO.java
 
b/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/OtherTestEventDTO.java
index d4739f8..222c911 100644
--- 
a/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/OtherTestEventDTO.java
+++ 
b/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/OtherTestEventDTO.java
@@ -19,7 +19,6 @@
 
 package org.apache.james.eventsourcing.eventstore.cassandra.dto;
 
-import org.apache.james.eventsourcing.Event;
 import org.apache.james.eventsourcing.EventId;
 import org.apache.james.eventsourcing.TestAggregateId;
 
@@ -27,7 +26,7 @@ import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-public class OtherTestEventDTO implements EventDTO {
+public class OtherTestEventDTO implements EventDTO<OtherEvent> {
     private final String type;
     private final long data;
     private final int eventId;
@@ -63,7 +62,7 @@ public class OtherTestEventDTO implements EventDTO {
 
     @JsonIgnore
     @Override
-    public Event toEvent() {
+    public OtherEvent toEvent() {
         return new OtherEvent(
             EventId.fromSerialized(eventId),
             TestAggregateId.testId(aggregate),
diff --git 
a/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/TestEventDTO.java
 
b/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/TestEventDTO.java
index 709c709..17d191a 100644
--- 
a/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/TestEventDTO.java
+++ 
b/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/TestEventDTO.java
@@ -28,7 +28,7 @@ import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-public class TestEventDTO implements EventDTO {
+public class TestEventDTO implements EventDTO<TestEvent> {
     private final String type;
     private final String data;
     private final int eventId;
@@ -64,7 +64,7 @@ public class TestEventDTO implements EventDTO {
 
     @JsonIgnore
     @Override
-    public Event toEvent() {
+    public TestEvent toEvent() {
         return new TestEvent(
             EventId.fromSerialized(eventId),
             TestAggregateId.testId(aggregate),
diff --git 
a/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/TestEventDTOModules.java
 
b/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/TestEventDTOModules.java
index 1040380..2aed742 100644
--- 
a/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/TestEventDTOModules.java
+++ 
b/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/TestEventDTOModules.java
@@ -23,8 +23,8 @@ import org.apache.james.eventsourcing.TestEvent;
 
 public interface TestEventDTOModules {
 
-    EventDTOModule<TestEvent, TestEventDTO> TEST_TYPE =
-        EventDTOModule
+
+    EventDTOModule TEST_TYPE = EventDTOModule
             .forEvent(TestEvent.class)
             .convertToDTO(TestEventDTO.class)
             .convertWith((event, typeName) -> new TestEventDTO(
@@ -32,16 +32,18 @@ public interface TestEventDTOModules {
                 event.getData(),
                 event.eventId().serialize(),
                 event.getAggregateId().getId()))
-            .typeName("TestType");
+            .typeName("TestType")
+            .withFactory(EventDTOModule::new);
 
-    EventDTOModule<OtherEvent, OtherTestEventDTO> OTHER_TEST_TYPE =
+    EventDTOModule OTHER_TEST_TYPE =
         EventDTOModule
             .forEvent(OtherEvent.class)
             .convertToDTO(OtherTestEventDTO.class)
-            .convertWith(((event, typeName) -> new OtherTestEventDTO(
+            .convertWith((event, typeName) -> new OtherTestEventDTO(
                 typeName,
                 event.getPayload(),
                 event.eventId().serialize(),
-                event.getAggregateId().getId())))
-            .typeName("other-type");
+                event.getAggregateId().getId()))
+            .typeName("other-type")
+            .withFactory(EventDTOModule::new);
 }
diff --git a/event-sourcing/event-store-cassandra/pom.xml b/json/pom.xml
similarity index 54%
copy from event-sourcing/event-store-cassandra/pom.xml
copy to json/pom.xml
index 12e4f21..7ede601 100644
--- a/event-sourcing/event-store-cassandra/pom.xml
+++ b/json/pom.xml
@@ -17,69 +17,21 @@
     specific language governing permissions and limitations
     under the License.
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
-    <modelVersion>4.0.0</modelVersion>
-
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
     <parent>
+        <artifactId>james-project</artifactId>
         <groupId>org.apache.james</groupId>
-        <artifactId>event-sourcing</artifactId>
         <version>3.4.0-SNAPSHOT</version>
     </parent>
+    <modelVersion>4.0.0</modelVersion>
 
-    <artifactId>event-sourcing-event-store-cassandra</artifactId>
+    <artifactId>james-json</artifactId>
 
-    <name>Apache James :: Event sourcing :: Event Store :: Cassandra</name>
-    <description>Cassandra implementation for James Event Store</description>
+    <name>Apache James :: Json serialization</name>
+    <description>Provides basic support for Json serialization of domain 
objects</description>
 
     <dependencies>
         <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-backends-cassandra</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-backends-cassandra</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>event-sourcing-core</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>event-sourcing-event-store-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>event-sourcing-event-store-api</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>event-sourcing-core</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>event-sourcing-pojo</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.assertj</groupId>
-            <artifactId>assertj-core</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
         </dependency>
@@ -96,13 +48,17 @@
             <artifactId>jackson-datatype-jsr310</artifactId>
         </dependency>
         <dependency>
+            <groupId>com.github.steveash.guavate</groupId>
+            <artifactId>guavate</artifactId>
+        </dependency>
+        <dependency>
             <groupId>net.javacrumbs.json-unit</groupId>
             <artifactId>json-unit-assertj</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>nl.jqno.equalsverifier</groupId>
-            <artifactId>equalsverifier</artifactId>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -111,21 +67,19 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.junit.platform</groupId>
-            <artifactId>junit-platform-launcher</artifactId>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-params</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-launcher</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.testcontainers</groupId>
-            <artifactId>testcontainers</artifactId>
-            <scope>test</scope>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
         </dependency>
     </dependencies>
 
-
-</project>
\ No newline at end of file
+</project>
diff --git a/json/src/main/java/org/apache/james/json/DTO.java 
b/json/src/main/java/org/apache/james/json/DTO.java
new file mode 100644
index 0000000..b0e8564
--- /dev/null
+++ b/json/src/main/java/org/apache/james/json/DTO.java
@@ -0,0 +1,5 @@
+package org.apache.james.json;
+
+public interface DTO<T> {
+    T toDomainObject();
+}
diff --git a/json/src/main/java/org/apache/james/json/DTOModule.java 
b/json/src/main/java/org/apache/james/json/DTOModule.java
new file mode 100644
index 0000000..8baeb8f
--- /dev/null
+++ b/json/src/main/java/org/apache/james/json/DTOModule.java
@@ -0,0 +1,114 @@
+/****************************************************************
+ * 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;
+
+public class DTOModule<T, U extends DTO<T>> {
+
+    public interface DTOConverter<T, U extends DTO<T>> {
+        U convert(T domainObject, String typeName);
+    }
+
+    public interface ModuleFactory<T, U extends DTO<T>, ModuleTypeT extends 
DTOModule<T, U>> {
+        ModuleTypeT create(DTOConverter<T, U> converter, Class<T> 
domainObjectType, Class<U> dtoType, String typeName);
+    }
+
+    public static <T> Builder<T> forDomainObject(Class<T> domainObjectType) {
+        return new Builder<>(domainObjectType);
+    }
+
+    public static class Builder<T> {
+
+        private final Class<T> type;
+
+        public Builder(Class<T> type) {
+            this.type = type;
+        }
+
+        public <U extends DTO<T>> RequireConversionFunctionBuilder<U> 
convertToDTO(Class<U> dtoType) {
+            return new RequireConversionFunctionBuilder<>(dtoType);
+        }
+
+        public class RequireConversionFunctionBuilder<U extends DTO<T>> {
+
+            private final Class<U> dtoType;
+
+            private RequireConversionFunctionBuilder(Class<U> dtoType) {
+                this.dtoType = dtoType;
+            }
+
+            public RequireTypeNameBuilder convertWith(DTOConverter<T, U> 
converter) {
+                return new RequireTypeNameBuilder(converter);
+            }
+
+            public class RequireTypeNameBuilder {
+                private final DTOConverter<T, U> converter;
+
+                private RequireTypeNameBuilder(DTOConverter<T, U> converter) {
+                    this.converter = converter;
+                }
+
+                public RequireModuleFactory typeName(String typeName) {
+                    return new RequireModuleFactory(typeName);
+                }
+
+                public class RequireModuleFactory {
+
+                    private final String typeName;
+
+                    private RequireModuleFactory(String typeName) {
+                        this.typeName = typeName;
+                    }
+
+                    public <ModuleTypeT extends DTOModule<T, U>> ModuleTypeT 
withFactory(ModuleFactory<T, U, ModuleTypeT> factory) {
+                        return factory.create(converter, type, dtoType, 
typeName);
+                    }
+                }
+            }
+        }
+    }
+
+    private final DTOConverter<T, U> converter;
+    private final Class<T> domainObjectType;
+    private final Class<U> dtoType;
+    private final String typeName;
+
+    protected DTOModule(DTOConverter<T, U> converter, Class<T> 
domainObjectType, Class<U> dtoType, String typeName) {
+        this.converter = converter;
+        this.domainObjectType = domainObjectType;
+        this.dtoType = dtoType;
+        this.typeName = typeName;
+    }
+
+    public String getDomainObjectType() {
+        return typeName;
+    }
+
+    public Class<U> getDTOClass() {
+        return dtoType;
+    }
+
+    public Class<T> getDomainObjectClass() {
+        return domainObjectType;
+    }
+
+    public U toDTO(T domainObject) {
+        return converter.convert(domainObject, typeName);
+    }
+}
diff --git 
a/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/JsonEventSerializer.java
 b/json/src/main/java/org/apache/james/json/JsonGenericSerializer.java
similarity index 61%
copy from 
event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/JsonEventSerializer.java
copy to json/src/main/java/org/apache/james/json/JsonGenericSerializer.java
index 2ab9019..cd8283d 100644
--- 
a/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/JsonEventSerializer.java
+++ b/json/src/main/java/org/apache/james/json/JsonGenericSerializer.java
@@ -17,7 +17,7 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.eventsourcing.eventstore.cassandra;
+package org.apache.james.json;
 
 import java.io.IOException;
 import java.util.Map;
@@ -25,12 +25,6 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
 
-import javax.inject.Inject;
-
-import org.apache.james.eventsourcing.Event;
-import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTO;
-import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTOModule;
-
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
@@ -41,21 +35,23 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
 import com.github.steveash.guavate.Guavate;
 import com.google.common.collect.ImmutableSet;
 
-public class JsonEventSerializer {
-    public static class UnknownEventException extends RuntimeException {
-        public UnknownEventException(String message) {
+public class JsonGenericSerializer<T, U extends DTO<T>> {
+    public static class UnknownTypeException extends RuntimeException {
+        public UnknownTypeException(String message) {
             super(message);
         }
     }
 
-    @SuppressWarnings("rawtypes")
-    private final Map<Class<? extends Event>, EventDTOModule> 
eventClassToModule;
-    @SuppressWarnings("rawtypes")
-    private final Map<String, EventDTOModule> typeToModule;
+    private final Map<Class<? extends T>, DTOModule<T, U>> domainClassToModule;
+    private final Map<String, DTOModule<T, U>> typeToModule;
     private final ObjectMapper objectMapper;
 
-    @Inject
-    public JsonEventSerializer(@SuppressWarnings("rawtypes") 
Set<EventDTOModule> modules) {
+    @SafeVarargs
+    public static <T, U extends DTO<T>> JsonGenericSerializer of(DTOModule<T, 
U>... modules) {
+        return new JsonGenericSerializer<>(ImmutableSet.copyOf(modules));
+    }
+
+    public JsonGenericSerializer(Set<DTOModule<T, U>> modules) {
         objectMapper = new ObjectMapper();
         objectMapper.registerModule(new Jdk8Module());
         objectMapper.registerModule(new JavaTimeModule());
@@ -64,43 +60,37 @@ public class JsonEventSerializer {
 
         typeToModule = modules.stream()
             .collect(Guavate.toImmutableMap(
-                EventDTOModule::getType,
+                DTOModule::getDomainObjectType,
                 Function.identity()));
 
-        eventClassToModule = modules.stream()
+        domainClassToModule = modules.stream()
             .collect(Guavate.toImmutableMap(
-                EventDTOModule::getEventClass,
+                DTOModule::getDomainObjectClass,
                 Function.identity()));
     }
-    
-    public JsonEventSerializer(@SuppressWarnings("rawtypes") EventDTOModule... 
modules) {
-        this(ImmutableSet.copyOf(modules));
-    }
 
-    public String serialize(Event event) throws JsonProcessingException {
-        @SuppressWarnings("unchecked")
-        EventDTO dto = 
Optional.ofNullable(eventClassToModule.get(event.getClass()))
-            .orElseThrow(() -> new UnknownEventException("unknown event class 
" + event.getClass()))
-            .toDTO(event);
+    public String serialize(T domainObject) throws JsonProcessingException {
+        U dto = 
Optional.ofNullable(domainClassToModule.get(domainObject.getClass()))
+            .orElseThrow(() -> new UnknownTypeException("unknown type " + 
domainObject.getClass()))
+            .toDTO(domainObject);
         return objectMapper.writeValueAsString(dto);
     }
 
-    public Event deserialize(String value) throws IOException {
+    public T deserialize(String value) throws IOException {
         JsonNode jsonNode = objectMapper.readTree(value);
 
         String type = jsonNode.path("type").asText();
 
-        EventDTO dto = objectMapper.readValue(
+        U dto = objectMapper.readValue(
             objectMapper.treeAsTokens(jsonNode),
             retrieveDTOClass(type));
-        return dto.toEvent();
+        return dto.toDomainObject();
     }
 
-    @SuppressWarnings("unchecked")
-    public Class<? extends EventDTO> retrieveDTOClass(String type) {
+    private Class<? extends U> retrieveDTOClass(String type) {
         return Optional.ofNullable(typeToModule.get(type))
-            .map(EventDTOModule::getDTOClass)
-            .orElseThrow(() -> new UnknownEventException("unknown event type " 
+ type));
+            .map(DTOModule::getDTOClass)
+            .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
new file mode 100644
index 0000000..c69a400
--- /dev/null
+++ b/json/src/test/java/org/apache/JsonGenericSerializerTest.java
@@ -0,0 +1,114 @@
+/****************************************************************
+ * 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 net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+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.FirstDomainObject;
+import org.apache.dto.SecondDomainObject;
+import org.apache.dto.TestModules;
+import org.apache.james.json.DTO;
+import org.apache.james.json.JsonGenericSerializer;
+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 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 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\"}";
+
+    @Test
+    void shouldDeserializeKnownType() throws Exception {
+        assertThat(JsonGenericSerializer.of(TestModules.FIRST_TYPE)
+            .deserialize(FIRST_JSON))
+            .isEqualTo(FIRST);
+    }
+
+    @Test
+    void shouldThrowWhenDeserializeUnknownType() {
+        assertThatThrownBy(() -> JsonGenericSerializer.of()
+            .deserialize(FIRST_JSON))
+            .isInstanceOf(JsonGenericSerializer.UnknownTypeException.class);
+    }
+
+    @ParameterizedTest
+    @MethodSource
+    void serializeShouldHandleAllKnownTypes(BaseType domainObject, String 
serializedJson) throws Exception {
+        JsonGenericSerializer<BaseType, DTO<BaseType>> serializer = 
JsonGenericSerializer.of(
+                TestModules.FIRST_TYPE,
+                TestModules.SECOND_TYPE);
+
+        assertThatJson(serializer.serialize(domainObject))
+            .isEqualTo(serializedJson);
+    }
+
+    private static Stream<Arguments> serializeShouldHandleAllKnownTypes() {
+        return allKnownTypes();
+    }
+
+    @ParameterizedTest
+    @MethodSource
+    void deserializeShouldHandleAllKnownTypes(BaseType domainObject, String 
serializedJson) throws Exception {
+        JsonGenericSerializer serializer = JsonGenericSerializer.of(
+                TestModules.FIRST_TYPE,
+                TestModules.SECOND_TYPE);
+
+        assertThatJson(serializer.deserialize(serializedJson))
+            .isEqualTo(domainObject);
+    }
+
+    private static Stream<Arguments> deserializeShouldHandleAllKnownTypes() {
+        return allKnownTypes();
+    }
+
+    private static Stream<Arguments> allKnownTypes() {
+        return Stream.of(
+                Arguments.of(SECOND, SECOND_JSON),
+                Arguments.of(FIRST, FIRST_JSON)
+        );
+    }
+
+    @Test
+    void shouldSerializeKnownType() throws Exception {
+        assertThatJson(JsonGenericSerializer.of(TestModules.FIRST_TYPE)
+            .serialize(FIRST))
+            .isEqualTo(FIRST_JSON);
+    }
+
+    @Test
+    void shouldThrowWhenSerializeUnknownType() {
+        assertThatThrownBy(() -> JsonGenericSerializer.of()
+            .serialize(FIRST))
+            .isInstanceOf(JsonGenericSerializer.UnknownTypeException.class);
+    }
+
+}
\ No newline at end of file
diff --git a/json/src/test/java/org/apache/dto/BaseType.java 
b/json/src/test/java/org/apache/dto/BaseType.java
new file mode 100644
index 0000000..e2eb2e7
--- /dev/null
+++ b/json/src/test/java/org/apache/dto/BaseType.java
@@ -0,0 +1,4 @@
+package org.apache.dto;
+
+public interface BaseType {
+}
diff --git 
a/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/OtherTestEventDTO.java
 b/json/src/test/java/org/apache/dto/FirstDTO.java
similarity index 62%
copy from 
event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/OtherTestEventDTO.java
copy to json/src/test/java/org/apache/dto/FirstDTO.java
index d4739f8..f8b1496 100644
--- 
a/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/OtherTestEventDTO.java
+++ b/json/src/test/java/org/apache/dto/FirstDTO.java
@@ -17,56 +17,54 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.eventsourcing.eventstore.cassandra.dto;
+package org.apache.dto;
 
-import org.apache.james.eventsourcing.Event;
-import org.apache.james.eventsourcing.EventId;
-import org.apache.james.eventsourcing.TestAggregateId;
+import java.time.ZonedDateTime;
+import java.util.Optional;
+
+import org.apache.james.json.DTO;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-public class OtherTestEventDTO implements EventDTO {
+public class FirstDTO implements DTO<FirstDomainObject> {
     private final String type;
-    private final long data;
-    private final int eventId;
-    private final int aggregate;
+    private final Optional<Long> id;
+    private final String time;
+    private final String payload;
 
     @JsonCreator
-    public OtherTestEventDTO(
+    public FirstDTO(
             @JsonProperty("type") String type,
-            @JsonProperty("data") long data,
-            @JsonProperty("eventId") int eventId,
-            @JsonProperty("aggregate") int aggregate) {
+            @JsonProperty("id") Optional<Long> id,
+            @JsonProperty("time") String time,
+            @JsonProperty("payload") String payload) {
         this.type = type;
-        this.data = data;
-        this.eventId = eventId;
-        this.aggregate = aggregate;
+        this.id = id;
+        this.time = time;
+        this.payload = payload;
     }
 
     public String getType() {
         return type;
     }
 
-    public long getData() {
-        return data;
+    public Optional<Long> getId() {
+        return id;
     }
 
-    public long getEventId() {
-        return eventId;
+    public String getTime() {
+        return time;
     }
 
-    public int getAggregate() {
-        return aggregate;
+    public String getPayload() {
+        return payload;
     }
 
     @JsonIgnore
     @Override
-    public Event toEvent() {
-        return new OtherEvent(
-            EventId.fromSerialized(eventId),
-            TestAggregateId.testId(aggregate),
-            data);
+    public FirstDomainObject toDomainObject() {
+        return new FirstDomainObject(id, ZonedDateTime.parse(time), payload);
     }
 }
diff --git 
a/server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationModules.java
 b/json/src/test/java/org/apache/dto/FirstDomainObject.java
similarity index 52%
copy from 
server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationModules.java
copy to json/src/test/java/org/apache/dto/FirstDomainObject.java
index c068900..6c8a787 100644
--- 
a/server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationModules.java
+++ b/json/src/test/java/org/apache/dto/FirstDomainObject.java
@@ -17,27 +17,47 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.dlp.eventsourcing.cassandra;
+package org.apache.dto;
 
-import org.apache.james.dlp.eventsourcing.events.ConfigurationItemsAdded;
-import org.apache.james.dlp.eventsourcing.events.ConfigurationItemsRemoved;
-import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTOModule;
+import java.time.ZonedDateTime;
+import java.util.Objects;
+import java.util.Optional;
 
-public interface DLPConfigurationModules {
+public class FirstDomainObject implements BaseType {
+    private final Optional<Long> id;
+    private final ZonedDateTime time;
+    private final String payload;
 
-    EventDTOModule<ConfigurationItemsAdded, DLPConfigurationItemAddedDTO> 
DLP_CONFIGURATION_STORE =
-        EventDTOModule
-            .forEvent(ConfigurationItemsAdded.class)
-            .convertToDTO(DLPConfigurationItemAddedDTO.class)
-            .convertWith(DLPConfigurationItemAddedDTO::from)
-            .typeName("dlp-configuration-store");
+    public FirstDomainObject(Optional<Long> id, ZonedDateTime time, String 
payload) {
+        this.id = id;
+        this.time = time;
+        this.payload = payload;
+    }
 
-    EventDTOModule<ConfigurationItemsRemoved, DLPConfigurationItemsRemovedDTO> 
DLP_CONFIGURATION_CLEAR =
-        EventDTOModule
-            .forEvent(ConfigurationItemsRemoved.class)
-            .convertToDTO(DLPConfigurationItemsRemovedDTO.class)
-            .convertWith(DLPConfigurationItemsRemovedDTO::from)
-            .typeName("dlp-configuration-clear");
+    public Optional<Long> getId() {
+        return id;
+    }
 
+    public ZonedDateTime getTime() {
+        return time;
+    }
 
+    public String getPayload() {
+        return payload;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        FirstDomainObject that = (FirstDomainObject) o;
+        return Objects.equals(id, that.id) &&
+                Objects.equals(time, that.time) &&
+                Objects.equals(payload, that.payload);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, time, payload);
+    }
 }
diff --git 
a/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/OtherTestEventDTO.java
 b/json/src/test/java/org/apache/dto/SecondDTO.java
similarity index 62%
copy from 
event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/OtherTestEventDTO.java
copy to json/src/test/java/org/apache/dto/SecondDTO.java
index d4739f8..b900100 100644
--- 
a/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/OtherTestEventDTO.java
+++ b/json/src/test/java/org/apache/dto/SecondDTO.java
@@ -17,56 +17,46 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.eventsourcing.eventstore.cassandra.dto;
+package org.apache.dto;
 
-import org.apache.james.eventsourcing.Event;
-import org.apache.james.eventsourcing.EventId;
-import org.apache.james.eventsourcing.TestAggregateId;
+import java.util.UUID;
+
+import org.apache.james.json.DTO;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-public class OtherTestEventDTO implements EventDTO {
+public class SecondDTO implements DTO<SecondDomainObject> {
     private final String type;
-    private final long data;
-    private final int eventId;
-    private final int aggregate;
+    private final String id;
+    private final String payload;
 
     @JsonCreator
-    public OtherTestEventDTO(
+    public SecondDTO(
             @JsonProperty("type") String type,
-            @JsonProperty("data") long data,
-            @JsonProperty("eventId") int eventId,
-            @JsonProperty("aggregate") int aggregate) {
+            @JsonProperty("id") String id,
+            @JsonProperty("payload") String payload) {
         this.type = type;
-        this.data = data;
-        this.eventId = eventId;
-        this.aggregate = aggregate;
+        this.id = id;
+        this.payload = payload;
     }
 
     public String getType() {
         return type;
     }
 
-    public long getData() {
-        return data;
-    }
-
-    public long getEventId() {
-        return eventId;
+    public String getId() {
+        return id;
     }
 
-    public int getAggregate() {
-        return aggregate;
+    public String getPayload() {
+        return payload;
     }
 
     @JsonIgnore
     @Override
-    public Event toEvent() {
-        return new OtherEvent(
-            EventId.fromSerialized(eventId),
-            TestAggregateId.testId(aggregate),
-            data);
+    public SecondDomainObject toDomainObject() {
+        return new SecondDomainObject(UUID.fromString(id), payload);
     }
 }
diff --git 
a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/FilteringRuleSetDefineDTOModules.java
 b/json/src/test/java/org/apache/dto/SecondDomainObject.java
similarity index 59%
copy from 
server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/FilteringRuleSetDefineDTOModules.java
copy to json/src/test/java/org/apache/dto/SecondDomainObject.java
index 2248eec..30ac702 100644
--- 
a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/FilteringRuleSetDefineDTOModules.java
+++ b/json/src/test/java/org/apache/dto/SecondDomainObject.java
@@ -17,20 +17,39 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.jmap.cassandra.filtering;
+package org.apache.dto;
 
-import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTOModule;
-import org.apache.james.jmap.api.filtering.impl.RuleSetDefined;
+import java.util.Objects;
+import java.util.UUID;
 
-public interface FilteringRuleSetDefineDTOModules {
+public class SecondDomainObject implements BaseType {
+    private final UUID id;
+    private final String payload;
 
-    String TYPE = "filtering-rule-set-defined";
+    public SecondDomainObject(UUID id, String payload) {
+        this.id = id;
+        this.payload = payload;
+    }
 
-    EventDTOModule<RuleSetDefined, FilteringRuleSetDefinedDTO> 
FILTERING_RULE_SET_DEFINED =
-        EventDTOModule
-            .forEvent(RuleSetDefined.class)
-            .convertToDTO(FilteringRuleSetDefinedDTO.class)
-            .convertWith(FilteringRuleSetDefinedDTO::from)
-            .typeName(TYPE);
+    public UUID getId() {
+        return id;
+    }
 
+    public String getPayload() {
+        return payload;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        SecondDomainObject that = (SecondDomainObject) o;
+        return Objects.equals(id, that.id) &&
+                Objects.equals(payload, that.payload);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, payload);
+    }
 }
diff --git 
a/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/EventDTO.java
 b/json/src/test/java/org/apache/dto/TestModule.java
similarity index 76%
copy from 
event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/EventDTO.java
copy to json/src/test/java/org/apache/dto/TestModule.java
index 461212a..afa4f2c 100644
--- 
a/event-sourcing/event-store-cassandra/src/main/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/EventDTO.java
+++ b/json/src/test/java/org/apache/dto/TestModule.java
@@ -17,10 +17,14 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.eventsourcing.eventstore.cassandra.dto;
+package org.apache.dto;
 
-import org.apache.james.eventsourcing.Event;
+import org.apache.james.json.DTO;
+import org.apache.james.json.DTOModule;
 
-public interface EventDTO {
-    Event toEvent();
+public class TestModule<T extends BaseType, U extends DTO<T>> extends 
DTOModule<T, U> {
+
+    protected TestModule(DTOConverter<T, U> converter, Class<T> 
domainObjectType, Class<U> dtoType, String typeName) {
+        super(converter, domainObjectType, dtoType, typeName);
+    }
 }
diff --git 
a/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/TestEventDTOModules.java
 b/json/src/test/java/org/apache/dto/TestModules.java
similarity index 56%
copy from 
event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/TestEventDTOModules.java
copy to json/src/test/java/org/apache/dto/TestModules.java
index 1040380..534f6ed 100644
--- 
a/event-sourcing/event-store-cassandra/src/test/java/org/apache/james/eventsourcing/eventstore/cassandra/dto/TestEventDTOModules.java
+++ b/json/src/test/java/org/apache/dto/TestModules.java
@@ -17,31 +17,31 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.eventsourcing.eventstore.cassandra.dto;
+package org.apache.dto;
 
-import org.apache.james.eventsourcing.TestEvent;
+import org.apache.james.json.DTOModule;
 
-public interface TestEventDTOModules {
+public interface TestModules {
 
-    EventDTOModule<TestEvent, TestEventDTO> TEST_TYPE =
-        EventDTOModule
-            .forEvent(TestEvent.class)
-            .convertToDTO(TestEventDTO.class)
-            .convertWith((event, typeName) -> new TestEventDTO(
+    TestModule FIRST_TYPE = DTOModule
+            .forDomainObject(FirstDomainObject.class)
+            .convertToDTO(FirstDTO.class)
+            .convertWith((domainObject, typeName) -> new FirstDTO(
                 typeName,
-                event.getData(),
-                event.eventId().serialize(),
-                event.getAggregateId().getId()))
-            .typeName("TestType");
+                domainObject.getId(),
+                domainObject.getTime().toString(),
+                domainObject.getPayload()))
+            .typeName("first")
+            .withFactory(TestModule::new);
 
-    EventDTOModule<OtherEvent, OtherTestEventDTO> OTHER_TEST_TYPE =
-        EventDTOModule
-            .forEvent(OtherEvent.class)
-            .convertToDTO(OtherTestEventDTO.class)
-            .convertWith(((event, typeName) -> new OtherTestEventDTO(
+    TestModule SECOND_TYPE = DTOModule
+            .forDomainObject(SecondDomainObject.class)
+            .convertToDTO(SecondDTO.class)
+            .convertWith((domainObject, typeName) -> new SecondDTO(
                 typeName,
-                event.getPayload(),
-                event.eventId().serialize(),
-                event.getAggregateId().getId())))
-            .typeName("other-type");
+                domainObject.getId().toString(),
+                domainObject.getPayload()))
+            .typeName("second")
+            .withFactory(TestModule::new);
+
 }
diff --git 
a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaEventDTOModules.java
 
b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaEventDTOModules.java
index 1697d5e..8012a00 100644
--- 
a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaEventDTOModules.java
+++ 
b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaEventDTOModules.java
@@ -29,6 +29,7 @@ public interface QuotaEventDTOModules {
             .forEvent(QuotaThresholdChangedEvent.class)
             .convertToDTO(QuotaThresholdChangedEventDTO.class)
             .convertWith(QuotaThresholdChangedEventDTO::from)
-            .typeName("quota-threshold-change");
+            .typeName("quota-threshold-change")
+            .withFactory(EventDTOModule::new);
 
 }
diff --git 
a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java
 
b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java
index 6d1ab84..499f28f 100644
--- 
a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java
+++ 
b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java
@@ -28,7 +28,7 @@ import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-class QuotaThresholdChangedEventDTO implements EventDTO {
+class QuotaThresholdChangedEventDTO implements 
EventDTO<QuotaThresholdChangedEvent> {
 
     @JsonIgnore
     public static QuotaThresholdChangedEventDTO 
from(QuotaThresholdChangedEvent event, String type) {
diff --git a/pom.xml b/pom.xml
index 2021201..8fa9701 100644
--- a/pom.xml
+++ b/pom.xml
@@ -530,6 +530,7 @@
         <module>event-sourcing</module>
         <module>examples</module>
         <module>javax-mail-extension</module>
+        <module>json</module>
         <module>mailbox</module>
         <module>mailet</module>
         <module>mdn</module>
@@ -1240,6 +1241,11 @@
             </dependency>
             <dependency>
                 <groupId>${james.groupId}</groupId>
+                <artifactId>james-json</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>${james.groupId}</groupId>
                 <artifactId>james-server-blob</artifactId>
                 <version>${project.version}</version>
             </dependency>
diff --git 
a/server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationItemAddedDTO.java
 
b/server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationItemAddedDTO.java
index fd1776b..1545679 100644
--- 
a/server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationItemAddedDTO.java
+++ 
b/server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationItemAddedDTO.java
@@ -34,7 +34,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.Preconditions;
 
-class DLPConfigurationItemAddedDTO implements EventDTO {
+class DLPConfigurationItemAddedDTO implements 
EventDTO<ConfigurationItemsAdded> {
 
     public static DLPConfigurationItemAddedDTO from(ConfigurationItemsAdded 
event, String type) {
         return new DLPConfigurationItemAddedDTO(
diff --git 
a/server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationItemsRemovedDTO.java
 
b/server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationItemsRemovedDTO.java
index 6cdd865..5d3a80a 100644
--- 
a/server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationItemsRemovedDTO.java
+++ 
b/server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationItemsRemovedDTO.java
@@ -34,7 +34,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.Preconditions;
 
-class DLPConfigurationItemsRemovedDTO implements EventDTO {
+class DLPConfigurationItemsRemovedDTO implements 
EventDTO<ConfigurationItemsRemoved> {
 
     public static DLPConfigurationItemsRemovedDTO 
from(ConfigurationItemsRemoved event, String type) {
         return new DLPConfigurationItemsRemovedDTO(
diff --git 
a/server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationModules.java
 
b/server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationModules.java
index c068900..692aa0d 100644
--- 
a/server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationModules.java
+++ 
b/server/data/data-cassandra/src/main/java/org/apache/james/dlp/eventsourcing/cassandra/DLPConfigurationModules.java
@@ -30,14 +30,16 @@ public interface DLPConfigurationModules {
             .forEvent(ConfigurationItemsAdded.class)
             .convertToDTO(DLPConfigurationItemAddedDTO.class)
             .convertWith(DLPConfigurationItemAddedDTO::from)
-            .typeName("dlp-configuration-store");
+            .typeName("dlp-configuration-store")
+            .withFactory(EventDTOModule::new);
 
     EventDTOModule<ConfigurationItemsRemoved, DLPConfigurationItemsRemovedDTO> 
DLP_CONFIGURATION_CLEAR =
         EventDTOModule
             .forEvent(ConfigurationItemsRemoved.class)
             .convertToDTO(DLPConfigurationItemsRemovedDTO.class)
             .convertWith(DLPConfigurationItemsRemovedDTO::from)
-            .typeName("dlp-configuration-clear");
+            .typeName("dlp-configuration-clear")
+            .withFactory(EventDTOModule::new);
 
 
 }
diff --git 
a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/FilteringRuleSetDefineDTOModules.java
 
b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/FilteringRuleSetDefineDTOModules.java
index 2248eec..f8002f6 100644
--- 
a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/FilteringRuleSetDefineDTOModules.java
+++ 
b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/FilteringRuleSetDefineDTOModules.java
@@ -31,6 +31,7 @@ public interface FilteringRuleSetDefineDTOModules {
             .forEvent(RuleSetDefined.class)
             .convertToDTO(FilteringRuleSetDefinedDTO.class)
             .convertWith(FilteringRuleSetDefinedDTO::from)
-            .typeName(TYPE);
+            .typeName(TYPE)
+            .withFactory(EventDTOModule::new);
 
 }
diff --git 
a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/FilteringRuleSetDefinedDTO.java
 
b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/FilteringRuleSetDefinedDTO.java
index 0aa5bf6..b655711 100644
--- 
a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/FilteringRuleSetDefinedDTO.java
+++ 
b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/FilteringRuleSetDefinedDTO.java
@@ -21,7 +21,6 @@ package org.apache.james.jmap.cassandra.filtering;
 
 import java.util.Objects;
 
-import org.apache.james.eventsourcing.Event;
 import org.apache.james.eventsourcing.EventId;
 import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTO;
 import org.apache.james.jmap.api.filtering.impl.FilteringAggregateId;
@@ -32,7 +31,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.collect.ImmutableList;
 
-public class FilteringRuleSetDefinedDTO implements EventDTO {
+public class FilteringRuleSetDefinedDTO implements EventDTO<RuleSetDefined> {
 
     public static FilteringRuleSetDefinedDTO from(RuleSetDefined event, String 
type) {
         return new FilteringRuleSetDefinedDTO(
@@ -79,7 +78,7 @@ public class FilteringRuleSetDefinedDTO implements EventDTO {
 
     @JsonIgnore
     @Override
-    public Event toEvent() {
+    public RuleSetDefined toEvent() {
         return new RuleSetDefined(
             FilteringAggregateId.parse(aggregateId),
             EventId.fromSerialized(eventId),
diff --git 
a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/view/cassandra/configuration/CassandraMailQueueViewConfigurationModule.java
 
b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/view/cassandra/configuration/CassandraMailQueueViewConfigurationModule.java
index 74febbc..e3b4fc6 100644
--- 
a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/view/cassandra/configuration/CassandraMailQueueViewConfigurationModule.java
+++ 
b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/view/cassandra/configuration/CassandraMailQueueViewConfigurationModule.java
@@ -30,5 +30,6 @@ public interface CassandraMailQueueViewConfigurationModule {
             .forEvent(ConfigurationChanged.class)
             .convertToDTO(ConfigurationChangedDTO.class)
             .convertWith(ConfigurationChangedDTO::from)
-            .typeName(TYPE_NAME);
+            .typeName(TYPE_NAME)
+            .withFactory(EventDTOModule::new);
 }
diff --git 
a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/view/cassandra/configuration/ConfigurationChangedDTO.java
 
b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/view/cassandra/configuration/ConfigurationChangedDTO.java
index afb959a..80a8ab7 100644
--- 
a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/view/cassandra/configuration/ConfigurationChangedDTO.java
+++ 
b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/view/cassandra/configuration/ConfigurationChangedDTO.java
@@ -22,7 +22,6 @@ package 
org.apache.james.queue.rabbitmq.view.cassandra.configuration;
 import java.time.Duration;
 import java.util.Objects;
 
-import org.apache.james.eventsourcing.Event;
 import org.apache.james.eventsourcing.EventId;
 import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTO;
 
@@ -31,7 +30,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.Preconditions;
 
-class ConfigurationChangedDTO implements EventDTO {
+class ConfigurationChangedDTO implements EventDTO<ConfigurationChanged> {
 
     static ConfigurationChangedDTO from(ConfigurationChanged 
configurationChanged, String type) {
         Preconditions.checkNotNull(configurationChanged);
@@ -76,7 +75,7 @@ class ConfigurationChangedDTO implements EventDTO {
 
     @JsonIgnore
     @Override
-    public Event toEvent() {
+    public ConfigurationChanged toEvent() {
         return new ConfigurationChanged(
             () -> aggregateKey,
             EventId.fromSerialized(eventId),


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

Reply via email to