You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2020/12/21 07:29:41 UTC

[james-project] 16/17: JAMES-3481 Use Factory to create MailboxChange & State instance

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 c1d50f9274049e309df7cccb89afdde063e4dedc
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Thu Dec 17 16:41:00 2020 +0700

    JAMES-3481 Use Factory to create MailboxChange & State instance
---
 .../james/modules/mailbox/MemoryMailboxModule.java |   2 +
 .../james/jmap/api/change/MailboxChange.java       | 245 +++++++++++++--------
 .../change/MailboxChangeRepositoryContract.java    | 219 ++++++++++--------
 .../change/MemoryMailboxChangeRepositoryTest.java  |   8 +
 .../contract/MailboxChangesMethodContract.scala    |  91 ++++----
 .../memory/MemoryMailboxChangesMethodTest.java     |   6 +
 .../james/jmap/change/MailboxChangeListener.scala  |  19 +-
 .../james/jmap/method/MailboxChangesMethod.scala   |  10 +-
 .../jmap/change/MailboxChangeListenerTest.scala    |  51 +++--
 9 files changed, 386 insertions(+), 265 deletions(-)

diff --git a/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/mailbox/MemoryMailboxModule.java b/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/mailbox/MemoryMailboxModule.java
index 211efe6..6bd4002 100644
--- a/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/mailbox/MemoryMailboxModule.java
+++ b/server/container/guice/memory-guice/src/main/java/org/apache/james/modules/mailbox/MemoryMailboxModule.java
@@ -25,6 +25,7 @@ import javax.inject.Singleton;
 
 import org.apache.james.adapter.mailbox.UserRepositoryAuthenticator;
 import org.apache.james.adapter.mailbox.UserRepositoryAuthorizator;
+import org.apache.james.jmap.api.change.MailboxChange.State;
 import org.apache.james.jmap.api.change.MailboxChangeRepository;
 import org.apache.james.jmap.memory.change.MemoryMailboxChangeRepository;
 import org.apache.james.mailbox.AttachmentContentLoader;
@@ -95,6 +96,7 @@ public class MemoryMailboxModule extends AbstractModule {
         bind(UidProvider.class).to(InMemoryUidProvider.class);
         bind(MailboxId.Factory.class).to(InMemoryId.Factory.class);
         bind(MessageId.Factory.class).to(InMemoryMessageId.Factory.class);
+        bind(State.Factory.class).to(State.DefaultFactory.class);
 
         bind(BlobManager.class).to(StoreBlobManager.class);
         bind(SubscriptionManager.class).to(StoreSubscriptionManager.class);
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java
index 5613db9..ee5e1e7 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java
@@ -27,6 +27,7 @@ import java.util.Optional;
 import java.util.UUID;
 import java.util.stream.Stream;
 
+import javax.inject.Inject;
 import javax.mail.Flags;
 
 import org.apache.james.core.Username;
@@ -54,6 +55,18 @@ public class MailboxChange {
     public static class State {
         public static State INITIAL = of(UUID.fromString("2c9f1b12-b35a-43e6-9af2-0106fb53a943"));
 
+        public interface Factory {
+            State generate();
+        }
+
+        public static class DefaultFactory implements Factory {
+
+            @Override
+            public State generate() {
+                return of(UUID.randomUUID());
+            }
+        }
+
         public static State of(UUID value) {
             return new State(value);
         }
@@ -102,17 +115,17 @@ public class MailboxChange {
     }
 
     @FunctionalInterface
-    interface RequiredAccountId {
+    public interface RequiredAccountId {
         RequiredState accountId(AccountId accountId);
     }
 
     @FunctionalInterface
-    interface RequiredState {
+    public interface RequiredState {
         RequiredDate state(State state);
     }
 
     @FunctionalInterface
-    interface RequiredDate {
+    public interface RequiredDate {
         Builder date(ZonedDateTime date);
     }
 
@@ -163,111 +176,156 @@ public class MailboxChange {
         return accountId -> state -> date -> new Builder(accountId, state, date);
     }
 
-    public static Builder created(AccountId accountId, State state, ZonedDateTime date, List<MailboxId> created) {
-        return MailboxChange.builder()
-            .accountId(accountId)
-            .state(state)
-            .date(date)
-            .created(created);
-    }
-
-    public static Builder updated(AccountId accountId, State state, ZonedDateTime date, List<MailboxId> updated) {
-        return MailboxChange.builder()
-            .accountId(accountId)
-            .state(state)
-            .date(date)
-            .updated(updated);
-    }
-
-    public static Builder destroyed(AccountId accountId, State state, ZonedDateTime date, List<MailboxId> destroyed) {
-        return MailboxChange.builder()
-            .accountId(accountId)
-            .state(state)
-            .date(date)
-            .destroyed(destroyed);
-    }
+    public static class Factory {
+        private final Clock clock;
+        private final MailboxManager mailboxManager;
+        private final State.Factory stateFactory;
 
-    public static Optional<List<MailboxChange>> fromEvent(Event event, MailboxManager mailboxManager) {
-        ZonedDateTime now = ZonedDateTime.now(Clock.systemUTC());
-        if (event instanceof MailboxAdded) {
-            MailboxAdded mailboxAdded = (MailboxAdded) event;
-            return Optional.of(ImmutableList.of(MailboxChange.created(AccountId.fromUsername(mailboxAdded.getUsername()), State.of(UUID.randomUUID()), now, ImmutableList.of(mailboxAdded.getMailboxId())).build()));
+        @Inject
+        public Factory(Clock clock, MailboxManager mailboxManager, State.Factory stateFactory) {
+            this.clock = clock;
+            this.mailboxManager = mailboxManager;
+            this.stateFactory = stateFactory;
         }
-        if (event instanceof MailboxRenamed) {
-            MailboxRenamed mailboxRenamed = (MailboxRenamed) event;
 
-            MailboxChange ownerChange = MailboxChange.updated(AccountId.fromUsername(mailboxRenamed.getUsername()), State.of(UUID.randomUUID()), now, ImmutableList.of(mailboxRenamed.getMailboxId())).build();
-            Stream<MailboxChange> shareeChanges = getSharees(mailboxRenamed.getNewPath(), mailboxRenamed.getUsername(), mailboxManager)
-                .map(name -> MailboxChange.updated(AccountId.fromString(name), State.of(UUID.randomUUID()), now, ImmutableList.of(mailboxRenamed.getMailboxId()))
-                    .delegated()
-                    .build());
-
-            List<MailboxChange> blah = Stream.concat(Stream.of(ownerChange), shareeChanges).collect(Guavate.toImmutableList());
-            return Optional.of(blah);
-        }
-        if (event instanceof MailboxACLUpdated) {
-            MailboxACLUpdated mailboxACLUpdated = (MailboxACLUpdated) event;
+        public List<MailboxChange> fromEvent(Event event) {
+            ZonedDateTime now = ZonedDateTime.now(clock);
+            if (event instanceof MailboxAdded) {
+                MailboxAdded mailboxAdded = (MailboxAdded) event;
 
-            MailboxChange ownerChange = MailboxChange.updated(AccountId.fromUsername(mailboxACLUpdated.getUsername()), State.of(UUID.randomUUID()), now, ImmutableList.of(mailboxACLUpdated.getMailboxId())).build();
-            Stream<MailboxChange> shareeChanges = getSharees(mailboxACLUpdated.getMailboxPath(), mailboxACLUpdated.getUsername(), mailboxManager)
-                .map(name -> MailboxChange.updated(AccountId.fromString(name), State.of(UUID.randomUUID()), now, ImmutableList.of(mailboxACLUpdated.getMailboxId()))
-                    .delegated()
+                return ImmutableList.of(MailboxChange.builder()
+                    .accountId(AccountId.fromUsername(mailboxAdded.getUsername()))
+                    .state(stateFactory.generate())
+                    .date(now)
+                    .created(ImmutableList.of(mailboxAdded.getMailboxId()))
                     .build());
+            }
+            if (event instanceof MailboxRenamed) {
+                MailboxRenamed mailboxRenamed = (MailboxRenamed) event;
+
+                MailboxChange ownerChange = MailboxChange.builder()
+                    .accountId(AccountId.fromUsername(mailboxRenamed.getUsername()))
+                    .state(stateFactory.generate())
+                    .date(now)
+                    .updated(ImmutableList.of(mailboxRenamed.getMailboxId()))
+                    .build();
+
+                Stream<MailboxChange> shareeChanges = getSharees(mailboxRenamed.getNewPath(), mailboxRenamed.getUsername(), mailboxManager)
+                    .map(name -> MailboxChange.builder()
+                        .accountId(AccountId.fromString(name))
+                        .state(stateFactory.generate())
+                        .date(now)
+                        .updated(ImmutableList.of(mailboxRenamed.getMailboxId()))
+                        .delegated()
+                        .build());
 
-            return Optional.of(
-                Stream.concat(Stream.of(ownerChange), shareeChanges)
-                    .collect(Guavate.toImmutableList()));
-        }
-        if (event instanceof MailboxDeletion) {
-            MailboxDeletion mailboxDeletion = (MailboxDeletion) event;
-            return Optional.of(ImmutableList.of(MailboxChange.destroyed(AccountId.fromUsername(mailboxDeletion.getUsername()), State.of(UUID.randomUUID()), now, ImmutableList.of(mailboxDeletion.getMailboxId())).build()));
-        }
-        if (event instanceof Added) {
-            Added messageAdded = (Added) event;
+                return Stream.concat(Stream.of(ownerChange), shareeChanges)
+                    .collect(Guavate.toImmutableList());
+            }
+            if (event instanceof MailboxACLUpdated) {
+                MailboxACLUpdated mailboxACLUpdated = (MailboxACLUpdated) event;
+
+                MailboxChange ownerChange = MailboxChange.builder()
+                    .accountId(AccountId.fromUsername(mailboxACLUpdated.getUsername()))
+                    .state(stateFactory.generate())
+                    .date(now)
+                    .updated(ImmutableList.of(mailboxACLUpdated.getMailboxId()))
+                    .build();
+
+                Stream<MailboxChange> shareeChanges = getSharees(mailboxACLUpdated.getMailboxPath(), mailboxACLUpdated.getUsername(), mailboxManager)
+                    .map(name -> MailboxChange.builder()
+                        .accountId(AccountId.fromString(name))
+                        .state(stateFactory.generate())
+                        .date(now)
+                        .updated(ImmutableList.of(mailboxACLUpdated.getMailboxId()))
+                        .delegated()
+                        .build());
 
-            MailboxChange ownerChange = MailboxChange.updated(AccountId.fromUsername(messageAdded.getUsername()), State.of(UUID.randomUUID()), now, ImmutableList.of(messageAdded.getMailboxId())).build();
-            Stream<MailboxChange> shareeChanges = getSharees(messageAdded.getMailboxPath(), messageAdded.getUsername(), mailboxManager)
-                .map(name -> MailboxChange.updated(AccountId.fromString(name), State.of(UUID.randomUUID()), now, ImmutableList.of(messageAdded.getMailboxId()))
-                    .delegated()
+                return Stream.concat(Stream.of(ownerChange), shareeChanges)
+                    .collect(Guavate.toImmutableList());
+            }
+            if (event instanceof MailboxDeletion) {
+                MailboxDeletion mailboxDeletion = (MailboxDeletion) event;
+
+                return ImmutableList.of(MailboxChange.builder()
+                    .accountId(AccountId.fromUsername(mailboxDeletion.getUsername()))
+                    .state(stateFactory.generate())
+                    .date(now)
+                    .destroyed(ImmutableList.of(mailboxDeletion.getMailboxId()))
                     .build());
-
-            return Optional.of(
-                Stream.concat(Stream.of(ownerChange), shareeChanges)
-                    .collect(Guavate.toImmutableList()));
-        }
-        if (event instanceof FlagsUpdated) {
-            FlagsUpdated messageFlagUpdated = (FlagsUpdated) event;
-            boolean isSeenChanged = messageFlagUpdated.getUpdatedFlags()
-                .stream()
-                .anyMatch(flags -> flags.isChanged(Flags.Flag.SEEN));
-            if (isSeenChanged) {
-
-                MailboxChange ownerChange = MailboxChange.updated(AccountId.fromUsername(messageFlagUpdated.getUsername()), State.of(UUID.randomUUID()), now, ImmutableList.of(messageFlagUpdated.getMailboxId())).build();
-                Stream<MailboxChange> shareeChanges = getSharees(messageFlagUpdated.getMailboxPath(), messageFlagUpdated.getUsername(), mailboxManager)
-                    .map(name -> MailboxChange.updated(AccountId.fromString(name), State.of(UUID.randomUUID()), now, ImmutableList.of(messageFlagUpdated.getMailboxId()))
+            }
+            if (event instanceof Added) {
+                Added messageAdded = (Added) event;
+
+                MailboxChange ownerChange = MailboxChange.builder()
+                    .accountId(AccountId.fromUsername(messageAdded.getUsername()))
+                    .state(stateFactory.generate())
+                    .date(now)
+                    .updated(ImmutableList.of(messageAdded.getMailboxId()))
+                    .build();
+
+                Stream<MailboxChange> shareeChanges = getSharees(messageAdded.getMailboxPath(), messageAdded.getUsername(), mailboxManager)
+                    .map(name -> MailboxChange.builder()
+                        .accountId(AccountId.fromString(name))
+                        .state(stateFactory.generate())
+                        .date(now)
+                        .updated(ImmutableList.of(messageAdded.getMailboxId()))
                         .delegated()
                         .build());
 
-                return Optional.of(
-                    Stream.concat(Stream.of(ownerChange), shareeChanges)
-                        .collect(Guavate.toImmutableList()));
+                return Stream.concat(Stream.of(ownerChange), shareeChanges)
+                    .collect(Guavate.toImmutableList());
             }
-        }
-        if (event instanceof Expunged) {
-            Expunged expunged = (Expunged) event;
+            if (event instanceof FlagsUpdated) {
+                FlagsUpdated messageFlagUpdated = (FlagsUpdated) event;
+                boolean isSeenChanged = messageFlagUpdated.getUpdatedFlags()
+                    .stream()
+                    .anyMatch(flags -> flags.isChanged(Flags.Flag.SEEN));
+                if (isSeenChanged) {
+                    MailboxChange ownerChange = MailboxChange.builder()
+                        .accountId(AccountId.fromUsername(messageFlagUpdated.getUsername()))
+                        .state(stateFactory.generate())
+                        .date(now)
+                        .updated(ImmutableList.of(messageFlagUpdated.getMailboxId()))
+                        .build();
+
+                    Stream<MailboxChange> shareeChanges = getSharees(messageFlagUpdated.getMailboxPath(), messageFlagUpdated.getUsername(), mailboxManager)
+                        .map(name -> MailboxChange.builder()
+                            .accountId(AccountId.fromString(name))
+                            .state(stateFactory.generate())
+                            .date(now)
+                            .updated(ImmutableList.of(messageFlagUpdated.getMailboxId()))
+                            .delegated()
+                            .build());
+
+                    return Stream.concat(Stream.of(ownerChange), shareeChanges)
+                        .collect(Guavate.toImmutableList());
+                }
+            }
+            if (event instanceof Expunged) {
+                Expunged expunged = (Expunged) event;
+                MailboxChange ownerChange = MailboxChange.builder()
+                    .accountId(AccountId.fromUsername(expunged.getUsername()))
+                    .state(stateFactory.generate())
+                    .date(now)
+                    .updated(ImmutableList.of(expunged.getMailboxId()))
+                    .build();
+
+                Stream<MailboxChange> shareeChanges = getSharees(expunged.getMailboxPath(), expunged.getUsername(), mailboxManager)
+                    .map(name -> MailboxChange.builder()
+                        .accountId(AccountId.fromString(name))
+                        .state(stateFactory.generate())
+                        .date(now)
+                        .updated(ImmutableList.of(expunged.getMailboxId()))
+                        .delegated()
+                        .build());
 
-            MailboxChange ownerChange = MailboxChange.updated(AccountId.fromUsername(expunged.getUsername()), State.of(UUID.randomUUID()), now, ImmutableList.of(expunged.getMailboxId())).build();
-            Stream<MailboxChange> shareeChanges = getSharees(expunged.getMailboxPath(), expunged.getUsername(), mailboxManager)
-                .map(name -> MailboxChange.updated(AccountId.fromString(name), State.of(UUID.randomUUID()), now, ImmutableList.of(expunged.getMailboxId()))
-                    .delegated()
-                    .build());
+                return Stream.concat(Stream.of(ownerChange), shareeChanges)
+                    .collect(Guavate.toImmutableList());
+            }
 
-            return Optional.of(
-                Stream.concat(Stream.of(ownerChange), shareeChanges)
-                    .collect(Guavate.toImmutableList()));
+            return ImmutableList.of();
         }
-
-        return Optional.empty();
     }
 
     private static Stream<String> getSharees(MailboxPath path, Username username, MailboxManager mailboxManager) {
@@ -277,6 +335,7 @@ public class MailboxChange {
             return mailboxACL.getEntries().keySet()
                 .stream()
                 .filter(rfc4314Rights -> !rfc4314Rights.isNegative())
+                .filter(rfc4314Rights -> rfc4314Rights.getNameType().equals(MailboxACL.NameType.user))
                 .map(MailboxACL.EntryKey::getName);
         } catch (MailboxException e) {
             return Stream.of();
diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/MailboxChangeRepositoryContract.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/MailboxChangeRepositoryContract.java
index 293d448..5a65347 100644
--- a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/MailboxChangeRepositoryContract.java
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/MailboxChangeRepositoryContract.java
@@ -26,7 +26,6 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.time.ZonedDateTime;
 import java.util.Optional;
-import java.util.UUID;
 
 import org.apache.james.jmap.api.change.MailboxChange.Limit;
 import org.apache.james.jmap.api.change.MailboxChange.State;
@@ -41,15 +40,17 @@ import com.google.common.collect.ImmutableList;
 public interface MailboxChangeRepositoryContract {
     AccountId ACCOUNT_ID = AccountId.fromUsername(BOB);
     ZonedDateTime DATE = ZonedDateTime.now();
-    State STATE_0 = State.of(UUID.randomUUID());
+
+    State.Factory stateFactory();
 
     MailboxChangeRepository mailboxChangeRepository();
 
     @Test
     default void saveChangeShouldSuccess() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State state = stateFactory().generate();
 
-        MailboxChange change = MailboxChange.created(ACCOUNT_ID, STATE_0, DATE, ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change = MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(DATE).created(ImmutableList.of(TestId.of(1))).build();
 
         assertThatCode(() -> repository.save(change).block())
             .doesNotThrowAnyException();
@@ -66,10 +67,11 @@ public interface MailboxChangeRepositoryContract {
     @Test
     default void getLatestStateShouldReturnLastPersistedState() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
 
-        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
-        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(3))).build();
-        MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE).created(ImmutableList.of(TestId.of(4))).build();
+        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
+        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(3))).build();
+        MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(4))).build();
         repository.save(change1).block();
         repository.save(change2).block();
         repository.save(change3).block();
@@ -81,8 +83,9 @@ public interface MailboxChangeRepositoryContract {
     @Test
     default void saveChangeShouldFailWhenNoAccountId() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
 
-        MailboxChange change = MailboxChange.created(null, STATE_0, DATE, ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change = MailboxChange.builder().accountId(null).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(1))).build();
 
         assertThatThrownBy(() -> repository.save(change).block())
             .isInstanceOf(NullPointerException.class);
@@ -92,7 +95,7 @@ public interface MailboxChangeRepositoryContract {
     default void saveChangeShouldFailWhenNoState() {
         MailboxChangeRepository repository = mailboxChangeRepository();
 
-        MailboxChange change = MailboxChange.created(ACCOUNT_ID, null, DATE, ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change = MailboxChange.builder().accountId(ACCOUNT_ID).state(null).date(DATE).created(ImmutableList.of(TestId.of(1))).build();
 
         assertThatThrownBy(() -> repository.save(change).block())
             .isInstanceOf(NullPointerException.class);
@@ -101,63 +104,73 @@ public interface MailboxChangeRepositoryContract {
     @Test
     default void getChangesShouldSuccess() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(STATE_0).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(1))).build();
-        MailboxChange change = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE).updated(ImmutableList.of(TestId.of(1))).build();
-        repository.save(oldState).block();
-        repository.save(change).block();
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).updated(ImmutableList.of(TestId.of(1))).build();
+        repository.save(oldState);
+        repository.save(change);
 
-        assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block().getAllChanges())
+        assertThat(repository.getSinceState(ACCOUNT_ID, referenceState, Optional.empty()).block().getAllChanges())
             .hasSameElementsAs(change.getUpdated());
     }
 
     @Test
     default void getChangesShouldReturnEmptyWhenNoNewerState() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(STATE_0).date(DATE).created(ImmutableList.of(TestId.of(1))).build();
-        repository.save(oldState).block();
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE).created(ImmutableList.of(TestId.of(1))).build();
+        repository.save(oldState);
 
-        assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block().getAllChanges())
+        assertThat(repository.getSinceState(ACCOUNT_ID, referenceState, Optional.empty()).block().getAllChanges())
             .isEmpty();
     }
 
     @Test
     default void getChangesShouldReturnCurrentStateWhenNoNewerState() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(STATE_0).date(DATE).created(ImmutableList.of(TestId.of(1))).build();
-        repository.save(oldState).block();
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE).created(ImmutableList.of(TestId.of(1))).build();
+        repository.save(oldState);
 
-        assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block().getNewState())
+        assertThat(repository.getSinceState(ACCOUNT_ID, referenceState, Optional.empty()).block().getNewState())
             .isEqualTo(oldState.getState());
     }
 
     @Test
     default void getChangesShouldLimitChanges() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(STATE_0).date(DATE.minusHours(3)).created(ImmutableList.of(TestId.of(1))).build();
-        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
-        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(3))).build();
-        MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE).created(ImmutableList.of(TestId.of(4))).build();
-        repository.save(oldState).block();
-        repository.save(change1).block();
-        repository.save(change2).block();
-        repository.save(change3).block();
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(3)).created(ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
+        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(3))).build();
+        MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(4))).build();
+        repository.save(oldState);
+        repository.save(change1);
+        repository.save(change2);
+        repository.save(change3);
 
-        assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(3))).block().getCreated())
+        assertThat(repository.getSinceState(ACCOUNT_ID, referenceState, Optional.of(Limit.of(3))).block().getCreated())
             .containsExactlyInAnyOrder(TestId.of(2), TestId.of(3), TestId.of(4));
     }
 
     @Test
     default void getChangesShouldReturnAllFromInitial() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(STATE_0).date(DATE.minusHours(3)).created(ImmutableList.of(TestId.of(1))).build();
-        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
-        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(3))).build();
-        MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE).created(ImmutableList.of(TestId.of(4))).build();
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(3)).created(ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
+        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(3))).build();
+        MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(4))).build();
         repository.save(oldState).block();
         repository.save(change1).block();
         repository.save(change2).block();
@@ -170,12 +183,14 @@ public interface MailboxChangeRepositoryContract {
     @Test
     default void getChangesFromInitialShouldReturnNewState() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(STATE_0).date(DATE.minusHours(3)).created(ImmutableList.of(TestId.of(1))).build();
-        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
-        State state2 = State.of(UUID.randomUUID());
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(3)).created(ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
+        State state2 = stateFactory.generate();
         MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(state2).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(3))).build();
-        MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE).created(ImmutableList.of(TestId.of(4))).build();
+        MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(4))).build();
         repository.save(oldState).block();
         repository.save(change1).block();
         repository.save(change2).block();
@@ -189,108 +204,122 @@ public interface MailboxChangeRepositoryContract {
     @Test
     default void getChangesShouldLimitChangesWhenMaxChangesOmitted() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.created(ACCOUNT_ID, STATE_0, DATE.minusHours(2), ImmutableList.of(TestId.of(1))).build();
-        MailboxChange change1 = MailboxChange.created(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE.minusHours(1), ImmutableList.of(TestId.of(2), TestId.of(3), TestId.of(4), TestId.of(5), TestId.of(6))).build();
-        MailboxChange change2 = MailboxChange.created(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE, ImmutableList.of(TestId.of(7))).build();
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3), TestId.of(4), TestId.of(5), TestId.of(6))).build();
+        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(7))).build();
 
         repository.save(oldState).block();
         repository.save(change1).block();
         repository.save(change2).block();
 
-        assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block().getAllChanges())
+        assertThat(repository.getSinceState(ACCOUNT_ID, referenceState, Optional.empty()).block().getAllChanges())
             .hasSameElementsAs(change1.getCreated());
     }
 
     @Test
     default void getChangesShouldNotReturnMoreThanMaxChanges() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(STATE_0).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
-        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
-        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE).created(ImmutableList.of(TestId.of(4), TestId.of(5))).build();
-        repository.save(oldState).block();
-        repository.save(change1).block();
-        repository.save(change2).block();
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(4), TestId.of(5))).build();
+        repository.save(oldState);
+        repository.save(change1);
+        repository.save(change2);
 
-        assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(3))).block().getAllChanges())
+        assertThat(repository.getSinceState(ACCOUNT_ID, referenceState, Optional.of(Limit.of(3))).block().getAllChanges())
             .hasSameElementsAs(change1.getCreated());
     }
 
     @Test
     default void getChangesShouldReturnEmptyWhenNumberOfChangesExceedMaxChanges() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(STATE_0).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
-        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
-        repository.save(oldState).block();
-        repository.save(change1).block();
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+        repository.save(oldState);
+        repository.save(change1);
 
-        assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(1))).block().getAllChanges())
+        assertThat(repository.getSinceState(ACCOUNT_ID, referenceState, Optional.of(Limit.of(1))).block().getAllChanges())
             .isEmpty();
     }
 
     @Test
     default void getChangesShouldReturnNewState() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(STATE_0).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
-        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
-        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE).updated(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
-        repository.save(oldState).block();
-        repository.save(change1).block();
-        repository.save(change2).block();
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).updated(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+        repository.save(oldState);
+        repository.save(change1);
+        repository.save(change2);
 
-        assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block().getNewState())
+        assertThat(repository.getSinceState(ACCOUNT_ID, referenceState, Optional.empty()).block().getNewState())
             .isEqualTo(change2.getState());
     }
 
     @Test
     default void hasMoreChangesShouldBeTrueWhenMoreChanges() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(STATE_0).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
-        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
-        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE).updated(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
-        repository.save(oldState).block();
-        repository.save(change1).block();
-        repository.save(change2).block();
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).updated(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+        repository.save(oldState);
+        repository.save(change1);
+        repository.save(change2);
 
-        assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(1))).block().hasMoreChanges())
+        assertThat(repository.getSinceState(ACCOUNT_ID, referenceState, Optional.of(Limit.of(1))).block().hasMoreChanges())
             .isTrue();
     }
 
     @Test
     default void hasMoreChangesShouldBeFalseWhenNoMoreChanges() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(STATE_0).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
-        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
-        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE).updated(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
-        repository.save(oldState).block();
-        repository.save(change1).block();
-        repository.save(change2).block();
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+        MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).updated(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+        repository.save(oldState);
+        repository.save(change1);
+        repository.save(change2);
 
-        assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(4))).block().hasMoreChanges())
+        assertThat(repository.getSinceState(ACCOUNT_ID, referenceState, Optional.of(Limit.of(4))).block().hasMoreChanges())
             .isFalse();
     }
 
     @Test
     default void changesShouldBeStoredInTheirRespectiveType() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(STATE_0).date(DATE.minusHours(3)).created(ImmutableList.of(TestId.of(1))).build();
-        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2), TestId.of(3), TestId.of(4), TestId.of(5))).build();
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(3)).created(ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2), TestId.of(3), TestId.of(4), TestId.of(5))).build();
         MailboxChange change2 = MailboxChange.builder()
             .accountId(ACCOUNT_ID)
-            .state(State.of(UUID.randomUUID()))
+            .state(stateFactory.generate())
             .date(DATE.minusHours(1))
             .created(ImmutableList.of(TestId.of(6), TestId.of(7)))
             .updated(ImmutableList.of(TestId.of(2), TestId.of(3)))
             .destroyed(ImmutableList.of(TestId.of(4))).build();
         MailboxChange change3 = MailboxChange.builder()
             .accountId(ACCOUNT_ID)
-            .state(State.of(UUID.randomUUID()))
+            .state(stateFactory.generate())
             .date(DATE)
             .created(ImmutableList.of(TestId.of(8)))
             .updated(ImmutableList.of(TestId.of(6), TestId.of(7)))
@@ -301,7 +330,7 @@ public interface MailboxChangeRepositoryContract {
         repository.save(change2).block();
         repository.save(change3).block();
 
-        MailboxChanges mailboxChanges = repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(20))).block();
+        MailboxChanges mailboxChanges = repository.getSinceState(ACCOUNT_ID, referenceState, Optional.of(Limit.of(20))).block();
 
         SoftAssertions.assertSoftly(softly -> {
             softly.assertThat(mailboxChanges.getCreated()).containsExactlyInAnyOrder(TestId.of(2), TestId.of(3), TestId.of(4), TestId.of(5), TestId.of(6), TestId.of(7), TestId.of(8));
@@ -313,12 +342,14 @@ public interface MailboxChangeRepositoryContract {
     @Test
     default void getChangesShouldIgnoreDuplicatedValues() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.created(ACCOUNT_ID, STATE_0, DATE.minusHours(2), ImmutableList.of(TestId.of(1))).build();
-        MailboxChange change1 = MailboxChange.updated(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE.minusHours(1), ImmutableList.of(TestId.of(1), TestId.of(2))).build();
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).updated(ImmutableList.of(TestId.of(1), TestId.of(2))).build();
         MailboxChange change2 = MailboxChange.builder()
             .accountId(ACCOUNT_ID)
-            .state(State.of(UUID.randomUUID()))
+            .state(stateFactory.generate())
             .date(DATE)
             .created(ImmutableList.of(TestId.of(3)))
             .updated(ImmutableList.of(TestId.of(1), TestId.of(2)))
@@ -328,7 +359,7 @@ public interface MailboxChangeRepositoryContract {
         repository.save(change1).block();
         repository.save(change2).block();
 
-        MailboxChanges mailboxChanges = repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(3))).block();
+        MailboxChanges mailboxChanges = repository.getSinceState(ACCOUNT_ID, referenceState, Optional.of(Limit.of(3))).block();
         SoftAssertions.assertSoftly(softly -> {
             softly.assertThat(mailboxChanges.getUpdated()).containsExactly(TestId.of(1), TestId.of(2));
             softly.assertThat(mailboxChanges.getCreated()).containsExactly(TestId.of(3));
@@ -338,11 +369,13 @@ public interface MailboxChangeRepositoryContract {
     @Test
     default void getChangesShouldReturnDelegatedChanges() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange oldState = MailboxChange.created(ACCOUNT_ID, STATE_0, DATE.minusHours(2), ImmutableList.of(TestId.of(1))).build();
+        MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
         MailboxChange change1 = MailboxChange.builder()
             .accountId(ACCOUNT_ID)
-            .state(State.of(UUID.randomUUID()))
+            .state(stateFactory.generate())
             .date(DATE.minusHours(1))
             .updated(ImmutableList.of(TestId.of(1)))
             .delegated()
@@ -351,7 +384,7 @@ public interface MailboxChangeRepositoryContract {
         repository.save(oldState);
         repository.save(change1);
 
-        assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, STATE_0, Optional.empty()).block().getUpdated())
+        assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, referenceState, Optional.empty()).block().getUpdated())
             .containsExactly(TestId.of(1));
 
     }
@@ -359,21 +392,25 @@ public interface MailboxChangeRepositoryContract {
     @Test
     default void getChangesShouldFailWhenInvalidMaxChanges() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        MailboxChange currentState = MailboxChange.builder().accountId(ACCOUNT_ID).state(STATE_0).date(DATE).created(ImmutableList.of(TestId.of(1))).build();
-        MailboxChange change = MailboxChange.builder().accountId(ACCOUNT_ID).state(State.of(UUID.randomUUID())).date(DATE).created(ImmutableList.of(TestId.of(2))).build();
-        repository.save(currentState).block();
-        repository.save(change).block();
+        MailboxChange currentState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE).created(ImmutableList.of(TestId.of(1))).build();
+        MailboxChange change = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(2))).build();
+        repository.save(currentState);
+        repository.save(change);
 
-        assertThatThrownBy(() -> repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(-1))))
+        assertThatThrownBy(() -> repository.getSinceState(ACCOUNT_ID, referenceState, Optional.of(Limit.of(-1))))
             .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
     default void getChangesShouldFailWhenSinceStateNotFound() {
         MailboxChangeRepository repository = mailboxChangeRepository();
+        State.Factory stateFactory = stateFactory();
+        State referenceState = stateFactory.generate();
 
-        assertThatThrownBy(() -> repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block())
+        assertThatThrownBy(() -> repository.getSinceState(ACCOUNT_ID, referenceState, Optional.empty()).block())
             .isInstanceOf(ChangeNotFoundException.class);
     }
 }
diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/change/MemoryMailboxChangeRepositoryTest.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/change/MemoryMailboxChangeRepositoryTest.java
index 9079e65..6c3b74f 100644
--- a/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/change/MemoryMailboxChangeRepositoryTest.java
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/change/MemoryMailboxChangeRepositoryTest.java
@@ -19,20 +19,28 @@
 
 package org.apache.james.jmap.memory.change;
 
+import org.apache.james.jmap.api.change.MailboxChange;
 import org.apache.james.jmap.api.change.MailboxChangeRepository;
 import org.apache.james.jmap.api.change.MailboxChangeRepositoryContract;
 import org.junit.jupiter.api.BeforeEach;
 
 public class MemoryMailboxChangeRepositoryTest implements MailboxChangeRepositoryContract {
     MailboxChangeRepository mailboxChangeRepository;
+    MailboxChange.State.Factory stateFactory;
 
     @BeforeEach
     void setup() {
         mailboxChangeRepository = new MemoryMailboxChangeRepository();
+        stateFactory = new MailboxChange.State.DefaultFactory();
     }
 
     @Override
     public MailboxChangeRepository mailboxChangeRepository() {
         return mailboxChangeRepository;
     }
+
+    @Override
+    public MailboxChange.State.Factory stateFactory() {
+        return stateFactory;
+    }
 }
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
index 4467a54..c230dd5 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
@@ -63,6 +63,8 @@ case class TestId(value: Long) extends MailboxId {
 
 trait MailboxChangesMethodContract {
 
+  def stateFactory: State.Factory
+
   @BeforeEach
   def setUp(server: GuiceJamesServer): Unit = {
     server.getProbe(classOf[DataProbeImpl])
@@ -506,12 +508,12 @@ trait MailboxChangesMethodContract {
           .setBody(request)
           .build, new ResponseSpecBuilder().build)
         .post
-        .`then`
-          .statusCode(SC_OK)
-          .contentType(JSON)
-          .extract
-          .body
-          .asString
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
 
       assertThatJson(response)
         .whenIgnoringPaths("methodResponses[0][1].newState")
@@ -570,12 +572,12 @@ trait MailboxChangesMethodContract {
           .setBody(request)
           .build, new ResponseSpecBuilder().build)
         .post
-        .`then`
-          .statusCode(SC_OK)
-          .contentType(JSON)
-          .extract
-          .body
-          .asString
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
 
       assertThatJson(response)
         .whenIgnoringPaths("methodResponses[0][1].newState")
@@ -641,12 +643,12 @@ trait MailboxChangesMethodContract {
           .setBody(request)
           .build, new ResponseSpecBuilder().build)
         .post
-        .`then`
-          .statusCode(SC_OK)
-          .contentType(JSON)
-          .extract
-          .body
-          .asString
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
 
       assertThatJson(response)
         .whenIgnoringPaths("methodResponses[0][1].newState")
@@ -711,12 +713,12 @@ trait MailboxChangesMethodContract {
           .setBody(request)
           .build, new ResponseSpecBuilder().build)
         .post
-        .`then`
-          .statusCode(SC_OK)
-          .contentType(JSON)
-          .extract
-          .body
-          .asString
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
 
       assertThatJson(response)
         .whenIgnoringPaths("methodResponses[0][1].newState")
@@ -782,12 +784,12 @@ trait MailboxChangesMethodContract {
           .setBody(request)
           .build, new ResponseSpecBuilder().build)
         .post
-        .`then`
-          .statusCode(SC_OK)
-          .contentType(JSON)
-          .extract
-          .body
-          .asString
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
 
       assertThatJson(response)
         .whenIgnoringPaths("methodResponses[0][1].newState")
@@ -853,12 +855,12 @@ trait MailboxChangesMethodContract {
           .setBody(request)
           .build, new ResponseSpecBuilder().build)
         .post
-        .`then`
-          .statusCode(SC_OK)
-          .contentType(JSON)
-          .extract
-          .body
-          .asString
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
 
       assertThatJson(response)
         .whenIgnoringPaths("methodResponses[0][1].newState")
@@ -918,12 +920,12 @@ trait MailboxChangesMethodContract {
           .setBody(request)
           .build, new ResponseSpecBuilder().build)
         .post
-        .`then`
-          .statusCode(SC_OK)
-          .contentType(JSON)
-          .extract
-          .body
-          .asString
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
 
       assertThatJson(response)
         .whenIgnoringPaths("methodResponses[0][1].newState")
@@ -1545,9 +1547,10 @@ trait MailboxChangesMethodContract {
   }
 
   private def storeReferenceState(server: GuiceJamesServer, username: Username): State = {
-    val state: State = State.of(UUID.randomUUID())
+    val state: State = stateFactory.generate()
     val jmapGuiceProbe: JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe])
-    jmapGuiceProbe.saveMailboxChange(MailboxChange.updated(AccountId.fromUsername(username), state, ZonedDateTime.now(), List(TestId.of(0)).asJava).build)
+
+    jmapGuiceProbe.saveMailboxChange(MailboxChange.builder.accountId(AccountId.fromUsername(username)).state(state).date(ZonedDateTime.now()).updated(List(TestId.of(0)).asJava).build)
 
     state
   }
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
index eadfa66..93104a9 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
@@ -24,6 +24,7 @@ import static org.apache.james.MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.jmap.api.change.MailboxChange;
 import org.apache.james.jmap.rfc8621.contract.MailboxChangesMethodContract;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.junit.jupiter.api.extension.RegisterExtension;
@@ -35,4 +36,9 @@ public class MemoryMailboxChangesMethodTest implements MailboxChangesMethodContr
             .combineWith(IN_MEMORY_SERVER_AGGREGATE_MODULE)
             .overrideWith(new TestJMAPServerModule()))
         .build();
+
+    @Override
+    public MailboxChange.State.Factory stateFactory() {
+        return new MailboxChange.State.DefaultFactory();
+    }
 }
\ No newline at end of file
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/change/MailboxChangeListener.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/change/MailboxChangeListener.scala
index b577eb8..aba030f 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/change/MailboxChangeListener.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/change/MailboxChangeListener.scala
@@ -24,6 +24,7 @@ import org.apache.james.jmap.api.change.{MailboxChange, MailboxChangeRepository}
 import org.apache.james.mailbox.MailboxManager
 import org.apache.james.mailbox.events.MailboxListener.{MailboxEvent, ReactiveGroupMailboxListener}
 import org.apache.james.mailbox.events.{Event, Group}
+import org.apache.james.util.ReactorUtils.DEFAULT_CONCURRENCY
 import org.reactivestreams.Publisher
 import reactor.core.scala.publisher.{SFlux, SMono}
 
@@ -32,16 +33,14 @@ import scala.jdk.CollectionConverters._
 case class MailboxChangeListenerGroup() extends Group {}
 
 case class MailboxChangeListener @Inject() (mailboxChangeRepository: MailboxChangeRepository,
-                                            mailboxManager: MailboxManager) extends ReactiveGroupMailboxListener {
-
-  override def reactiveEvent(event: Event): Publisher[Void] = {
-    MailboxChange.fromEvent(event, mailboxManager)
-      .map(changes => SFlux.fromIterable(changes.asScala)
-        .map(change => mailboxChangeRepository.save(change))
-        .`then`()
-        .`then`(SMono.empty[Void]).asJava)
-      .orElse(SMono.empty[Void].asJava)
-  }
+                                            mailboxManager: MailboxManager,
+                                            mailboxChangeFactory: MailboxChange.Factory) extends ReactiveGroupMailboxListener {
+
+  override def reactiveEvent(event: Event): Publisher[Void] =
+    SFlux.fromIterable(mailboxChangeFactory.fromEvent(event).asScala)
+      .flatMap(change => mailboxChangeRepository.save(change), DEFAULT_CONCURRENCY)
+      .`then`()
+      .`then`(SMono.empty[Void]).asJava
 
   override def getDefaultGroup: Group = MailboxChangeListenerGroup()
 
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxChangesMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxChangesMethod.scala
index 5bbca81..c60e038 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxChangesMethod.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxChangesMethod.scala
@@ -46,12 +46,14 @@ class MailboxChangesMethod @Inject()(mailboxSerializer: MailboxSerializer,
   override val requiredCapabilities: Set[CapabilityIdentifier] = Set(JMAP_MAIL)
 
   override def doProcess(capabilities: Set[CapabilityIdentifier], invocation: InvocationWithContext, mailboxSession: MailboxSession, request: MailboxChangesRequest): SMono[InvocationWithContext] =
-    SMono.fromPublisher(
+    SMono.fromPublisher({
+      val accountId: JavaAccountId = JavaAccountId.fromUsername(mailboxSession.getUser)
+      val state: JavaState = JavaState.of(request.sinceState.value)
       if (capabilities.contains(CapabilityIdentifier.JAMES_SHARES)) {
-        mailboxChangeRepository.getSinceStateWithDelegation(JavaAccountId.fromUsername(mailboxSession.getUser), JavaState.of(request.sinceState.value), request.maxChanged.toJava)
+        mailboxChangeRepository.getSinceStateWithDelegation(accountId, state, request.maxChanged.toJava)
       } else {
-        mailboxChangeRepository.getSinceState(JavaAccountId.fromUsername(mailboxSession.getUser), JavaState.of(request.sinceState.value), request.maxChanged.toJava)
-      })
+        mailboxChangeRepository.getSinceState(accountId, state, request.maxChanged.toJava)
+      }})
       .map(mailboxChanges => MailboxChangesResponse(
         accountId = request.accountId,
         oldState = request.sinceState,
diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/change/MailboxChangeListenerTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/change/MailboxChangeListenerTest.scala
index aecbfc7..a207f72 100644
--- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/change/MailboxChangeListenerTest.scala
+++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/change/MailboxChangeListenerTest.scala
@@ -19,8 +19,7 @@
 
 package org.apache.james.jmap.change
 
-import java.time.ZonedDateTime
-import java.util.UUID
+import java.time.{Clock, ZonedDateTime}
 
 import javax.mail.Flags
 import org.apache.james.jmap.api.change.MailboxChange.State
@@ -50,7 +49,10 @@ class MailboxChangeListenerTest {
 
   var repository: MailboxChangeRepository = _
   var mailboxManager: MailboxManager = _
+  var mailboxChangeFactory: MailboxChange.Factory = _
+  var stateFactory: State.Factory = _
   var listener: MailboxChangeListener = _
+  var clock: Clock = _
 
   @BeforeEach
   def setUp: Unit = {
@@ -61,16 +63,19 @@ class MailboxChangeListenerTest {
       .defaultAnnotationLimits.defaultMessageParser.scanningSearchIndex.noPreDeletionHooks.storeQuotaManager
       .build
 
+    clock = Clock.systemUTC()
     mailboxManager = resources.getMailboxManager
+    stateFactory = new State.DefaultFactory
+    mailboxChangeFactory = new MailboxChange.Factory(clock, mailboxManager, stateFactory)
     repository = new MemoryMailboxChangeRepository()
-    listener = MailboxChangeListener(repository, mailboxManager)
+    listener = MailboxChangeListener(repository, mailboxManager, mailboxChangeFactory)
     resources.getEventBus.register(listener)
   }
 
   @Test
   def createMailboxShouldStoreCreatedEvent(): Unit = {
-    val state = State.of(UUID.randomUUID)
-    repository.save(MailboxChange.created(ACCOUNT_ID, state, ZonedDateTime.now, List[MailboxId](TestId.of(0)).asJava).build).block()
+    val state = stateFactory.generate()
+    repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
 
     val mailboxSession = MailboxSessionUtil.create(BOB)
     val inboxId: MailboxId = mailboxManager.createMailbox(MailboxPath.inbox(BOB), mailboxSession).get
@@ -86,8 +91,8 @@ class MailboxChangeListenerTest {
     val newPath = MailboxPath.forUser(BOB, "another")
     val inboxId: MailboxId = mailboxManager.createMailbox(path, mailboxSession).get
 
-    val state = State.of(UUID.randomUUID)
-    repository.save(MailboxChange.created(ACCOUNT_ID, state, ZonedDateTime.now, List[MailboxId](TestId.of(0)).asJava).build).block()
+    val state = stateFactory.generate()
+    repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
 
     mailboxManager.renameMailbox(path, newPath, mailboxSession)
 
@@ -97,8 +102,8 @@ class MailboxChangeListenerTest {
 
   @Test
   def updateMailboxACLShouldStoreUpdatedEvent(): Unit = {
-    val state = State.of(UUID.randomUUID)
-    repository.save(MailboxChange.created(ACCOUNT_ID, state, ZonedDateTime.now, List[MailboxId](TestId.of(0)).asJava).build).block()
+    val state = stateFactory.generate()
+    repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
 
     val mailboxSession = MailboxSessionUtil.create(BOB)
     val path = MailboxPath.inbox(BOB)
@@ -116,8 +121,8 @@ class MailboxChangeListenerTest {
     val path = MailboxPath.forUser(BOB, "test")
     val inboxId: MailboxId = mailboxManager.createMailbox(path, mailboxSession).get
 
-    val state = State.of(UUID.randomUUID)
-    repository.save(MailboxChange.created(ACCOUNT_ID, state, ZonedDateTime.now, List[MailboxId](TestId.of(0)).asJava).build).block()
+    val state = stateFactory.generate()
+    repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
 
     mailboxManager.applyRightsCommand(path, MailboxACL.command().forUser(ALICE).rights(MailboxACL.Right.Read).asAddition(), mailboxSession)
 
@@ -137,8 +142,8 @@ class MailboxChangeListenerTest {
     val messageManager: MessageManager = mailboxManager.getMailbox(inboxId, mailboxSession)
     messageManager.appendMessage(AppendCommand.builder().build("header: value\r\n\r\nbody"), mailboxSession)
 
-    val state = State.of(UUID.randomUUID)
-    repository.save(MailboxChange.created(ACCOUNT_ID, state, ZonedDateTime.now, List[MailboxId](TestId.of(0)).asJava).build).block()
+    val state = stateFactory.generate()
+    repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
 
     messageManager.setFlags(new Flags(Flags.Flag.SEEN), FlagsUpdateMode.ADD, MessageRange.all(), mailboxSession)
 
@@ -156,8 +161,8 @@ class MailboxChangeListenerTest {
       .withFlags(new Flags(Flags.Flag.SEEN))
       .build("header: value\r\n\r\nbody"), mailboxSession)
 
-    val state = State.of(UUID.randomUUID)
-    repository.save(MailboxChange.created(ACCOUNT_ID, state, ZonedDateTime.now, List[MailboxId](TestId.of(0)).asJava).build).block()
+    val state = stateFactory.generate()
+    repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
 
     messageManager.setFlags(new Flags(Flags.Flag.SEEN), FlagsUpdateMode.REMOVE, MessageRange.all(), mailboxSession)
 
@@ -173,8 +178,8 @@ class MailboxChangeListenerTest {
     val messageManager: MessageManager = mailboxManager.getMailbox(inboxId, mailboxSession)
     messageManager.appendMessage(AppendCommand.builder().build("header: value\r\n\r\nbody"), mailboxSession)
 
-    val state = State.of(UUID.randomUUID)
-    repository.save(MailboxChange.created(ACCOUNT_ID, state, ZonedDateTime.now, List[MailboxId](TestId.of(0)).asJava).build).block()
+    val state = stateFactory.generate()
+    repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
 
     messageManager.setFlags(new Flags(Flags.Flag.ANSWERED), FlagsUpdateMode.ADD, MessageRange.all(), mailboxSession)
 
@@ -192,8 +197,8 @@ class MailboxChangeListenerTest {
       .withFlags(new Flags(Flags.Flag.ANSWERED))
       .build("header: value\r\n\r\nbody"), mailboxSession)
 
-    val state = State.of(UUID.randomUUID)
-    repository.save(MailboxChange.created(ACCOUNT_ID, state, ZonedDateTime.now, List[MailboxId](TestId.of(0)).asJava).build).block()
+    val state = stateFactory.generate()
+    repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
 
     messageManager.setFlags(new Flags(Flags.Flag.DELETED), FlagsUpdateMode.REPLACE, MessageRange.all(), mailboxSession)
 
@@ -209,8 +214,8 @@ class MailboxChangeListenerTest {
     val messageManager: MessageManager = mailboxManager.getMailbox(inboxId, mailboxSession)
     val appendResult: AppendResult = messageManager.appendMessage(AppendCommand.builder().build("header: value\r\n\r\nbody"), mailboxSession)
 
-    val state = State.of(UUID.randomUUID)
-    repository.save(MailboxChange.created(ACCOUNT_ID, state, ZonedDateTime.now, List[MailboxId](TestId.of(0)).asJava).build).block()
+    val state = stateFactory.generate()
+    repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
     messageManager.delete(List(appendResult.getId.getUid).asJava, mailboxSession)
 
     assertThat(repository.getSinceState(ACCOUNT_ID, state, None.toJava).block().getUpdated)
@@ -223,8 +228,8 @@ class MailboxChangeListenerTest {
     val path = MailboxPath.forUser(BOB, "test")
     val inboxId: MailboxId = mailboxManager.createMailbox(path, mailboxSession).get
 
-    val state = State.of(UUID.randomUUID)
-    repository.save(MailboxChange.created(ACCOUNT_ID, state, ZonedDateTime.now, List[MailboxId](TestId.of(0)).asJava).build).block()
+    val state = stateFactory.generate()
+    repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
 
     mailboxManager.deleteMailbox(inboxId, mailboxSession)
 


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org