You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by rc...@apache.org on 2020/07/15 04:36:08 UTC

[james-project] branch master updated (9ecfcaa -> c4fafaf)

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

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


    from 9ecfcaa  [JAMES-3301] Removed antlib references, fixed formatting issue in markdown
     new 85ab0e3  JAMES-3295 Use MessageManager::listMessagesMetadata more widely
     new c74f883  JAMES-3305 Dont crash EventBus processing upon invalid messages
     new f0f598a  JAMES-3305 Helper for RabbitMQ DeadLetter queue option
     new 1de4fa5  JAMES-3305 Invalid EventBus messages needs to be stored in dead letter queue
     new 9996553  JAMES-3305 Key registration should not crash on invalid messages
     new cbf9001  [Refactor] Remove unused misleading wrong configuration files
     new 88ba426  JAMES-3266 Offer an option to disable ElasticSearch in Distributed James product
     new 106bba2  JAMES-3266 Document ElasticSearch opt-in/opt-out
     new c4fafaf  JAMES-3266 Move disable ElasticSearch option into a separate search.properties configuration file

The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/james/backends/rabbitmq/Constants.java  |   4 +
 .../james/mailbox/events/EventDispatcher.java      |  28 +++-
 .../james/mailbox/events/GroupRegistration.java    |  28 +++-
 .../james/mailbox/events/RabbitMQEventBus.java     |   2 +
 .../james/mailbox/events/RabbitMQEventBusTest.java | 106 ++++++++++++++-
 .../imap/processor/AbstractMailboxProcessor.java   |  15 ++-
 .../james/imap/processor/SearchProcessor.java      |  11 +-
 .../james/imap/processor/StoreProcessor.java       |  25 ++--
 server/container/guice/cassandra-guice/pom.xml     |   4 +
 .../james/CassandraJamesServerConfiguration.java}  |  36 +++--
 .../org/apache/james/CassandraJamesServerMain.java |  16 +--
 .../java/org/apache/james/SearchConfiguration.java |  82 ++++++++++++
 .../java/org/apache/james/SearchModuleChooser.java | 149 +++++++++++++++++++++
 .../AuthenticatedCassandraJamesServerTest.java     |   6 +-
 .../java/org/apache/james/CacheSessionTest.java    |   7 +-
 .../org/apache/james/CassandraJamesServerTest.java |   2 +-
 .../apache/james/CassandraJmapJamesServerTest.java |   2 +-
 .../org/apache/james/CassandraJmapTestRule.java    |   4 +-
 .../CassandraMailRepositoryIntegrationTest.java    |   2 +-
 .../CassandraMessageIdManagerInjectionTest.java    |   2 +-
 .../org/apache/james/CassandraNodeConfTest.java    |   2 +-
 .../org/apache/james/CassandraWithTikaTest.java    |   3 +-
 .../james/DefaultCassandraJamesServerTest.java     |   2 +-
 .../test/java/org/apache/james/ESReporterTest.java |   2 +-
 .../apache/james/JamesCapabilitiesServerTest.java  |   2 +-
 .../james/JamesServerWithRetryConnectionTest.java  |   2 +-
 ...esWithNonCompatibleElasticSearchServerTest.java |   2 +-
 .../org/apache/james/KeyspaceCreationTest.java     |   8 +-
 .../org/apache/james/SearchConfigurationTest.java  |  62 ++++-----
 ...a => TestingDistributedJamesServerBuilder.java} |  45 ++-----
 .../apache/james/WithCassandraBlobStoreTest.java   |   2 +-
 .../CassandraSchemaVersionStartUpCheckTest.java    |   9 +-
 .../apache/james/CassandraLdapJamesServerMain.java |   8 +-
 .../apache/james/CassandraLdapJamesServerTest.java |   2 +-
 .../james/CassandraLdapJmapJamesServerTest.java    |   2 +-
 .../src/test/resources/usersrepository.xml         |  31 -----
 .../james/CassandraRabbitMQJamesConfiguration.java |  28 +++-
 .../james/CassandraRabbitMQJamesServerMain.java    |   4 +-
 .../james/CassandraRabbitMQAwsS3JmapTestRule.java  |   1 +
 .../james/CassandraRabbitMQJamesServerFixture.java |   1 +
 .../james/CassandraRabbitMQSwiftJmapTestRule.java  |   1 +
 .../java/org/apache/james/WithCacheExtension.java  |   1 +
 .../org/apache/james/WithCassandraBlobStore.java   |   1 +
 ...nsion.java => WithScanningSearchExtension.java} |   8 +-
 ...hCacheTest.java => WithScanningSearchTest.java} |   4 +-
 .../CassandraRabbitMQLdapJamesServerMain.java      |   6 +-
 .../CassandraRabbitMQLdapJmapJamesServerTest.java  |   1 +
 .../src/test/resources/usersrepository.xml         |  31 -----
 .../jmap/cassandra/CassandraImapErrorTest.java     |   5 +-
 .../jmap/cassandra/CassandraSendMDNMethodTest.java |   5 +-
 .../CassandraSpamAssassinContractTest.java         |   5 +-
 .../jmap/cassandra/cucumber/CassandraStepdefs.java |   6 +-
 .../rabbitmq/RabbitMQAwsS3SendMDNMethodTest.java   |   2 +
 .../RabbitMQAwsS3SpamAssassinContractTest.java     |   2 +
 .../cucumber/awss3/RabbitMQAwsS3Stepdefs.java      |   2 +
 .../distributed/DistributedAuthenticationTest.java |   2 +
 .../distributed/DistributedEchoMethodTest.java     |   2 +
 .../rabbitmq/ConsistencyTasksIntegrationTest.java  |   2 +
 .../rabbitmq/FixingGhostMailboxTest.java           |   2 +
 .../rabbitmq/RabbitMQAuthorizedEndpointsTest.java  |   2 +
 .../RabbitMQEventDeadLettersIntegrationTest.java   |   2 +
 ...stViewProjectionHealthCheckIntegrationTest.java |   2 +
 .../rabbitmq/RabbitMQForwardIntegrationTest.java   |   2 +
 .../rabbitmq/RabbitMQJmapExtension.java            |   2 +
 .../rabbitmq/RabbitMQJwtFilterIntegrationTest.java |   2 +
 ...RabbitMQReindexingWithEventDeadLettersTest.java |   2 +
 .../RabbitMQWebAdminServerIntegrationTest.java     |   2 +
 ...dminServerTaskSerializationIntegrationTest.java |   2 +
 ...RabbitMQDeletedMessageVaultIntegrationTest.java |   2 +
 ...LinshareBlobExportMechanismIntegrationTest.java |   2 +
 .../jmap/MessageFastViewProjectionCorrector.java   |   7 +-
 .../queue/rabbitmq/RabbitMQMailQueueFactory.java   |   4 +-
 src/site/xdoc/server/config-elasticsearch.xml      |  10 ++
 73 files changed, 632 insertions(+), 248 deletions(-)
 copy server/container/guice/{cassandra-rabbitmq-guice/src/main/java/org/apache/james/CassandraRabbitMQJamesConfiguration.java => cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerConfiguration.java} (74%)
 create mode 100644 server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchConfiguration.java
 create mode 100644 server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchModuleChooser.java
 copy mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/RetentionConfigurationTest.java => server/container/guice/cassandra-guice/src/test/java/org/apache/james/SearchConfigurationTest.java (52%)
 copy server/container/guice/cassandra-guice/src/test/java/org/apache/james/{CassandraExtension.java => TestingDistributedJamesServerBuilder.java} (58%)
 delete mode 100644 server/container/guice/cassandra-ldap-guice/src/test/resources/usersrepository.xml
 copy server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/{WithCacheExtension.java => WithScanningSearchExtension.java} (93%)
 copy server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/{WithCacheTest.java => WithScanningSearchTest.java} (89%)
 delete mode 100644 server/container/guice/cassandra-rabbitmq-ldap-guice/src/test/resources/usersrepository.xml


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


[james-project] 02/09: JAMES-3305 Dont crash EventBus processing upon invalid messages

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c74f8833dae8a746939ee94ec46f5d5fca7abeac
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Fri Jul 10 11:01:02 2020 +0700

    JAMES-3305 Dont crash EventBus processing upon invalid messages
---
 .../james/mailbox/events/GroupRegistration.java    | 23 ++++++++++---
 .../james/mailbox/events/RabbitMQEventBusTest.java | 40 ++++++++++++++++++++++
 2 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/GroupRegistration.java b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/GroupRegistration.java
index cade1c8..d95e6bd 100644
--- a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/GroupRegistration.java
+++ b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/GroupRegistration.java
@@ -24,6 +24,7 @@ import static org.apache.james.backends.rabbitmq.Constants.DURABLE;
 import static org.apache.james.backends.rabbitmq.Constants.EMPTY_ROUTING_KEY;
 import static org.apache.james.backends.rabbitmq.Constants.EXCLUSIVE;
 import static org.apache.james.backends.rabbitmq.Constants.NO_ARGUMENTS;
+import static org.apache.james.backends.rabbitmq.Constants.REQUEUE;
 import static org.apache.james.mailbox.events.RabbitMQEventBus.MAILBOX_EVENT;
 import static org.apache.james.mailbox.events.RabbitMQEventBus.MAILBOX_EVENT_EXCHANGE_NAME;
 
@@ -35,6 +36,8 @@ import java.util.function.Predicate;
 import org.apache.james.backends.rabbitmq.ReceiverProvider;
 import org.apache.james.event.json.EventSerializer;
 import org.apache.james.util.MDCBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Preconditions;
 
@@ -70,6 +73,7 @@ class GroupRegistration implements Registration {
         }
     }
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(GroupRegistration.class);
     static final String RETRY_COUNT = "retry-count";
     static final int DEFAULT_RETRY_COUNT = 0;
 
@@ -138,13 +142,22 @@ class GroupRegistration implements Registration {
 
     private Mono<Void> deliver(AcknowledgableDelivery acknowledgableDelivery) {
         byte[] eventAsBytes = acknowledgableDelivery.getBody();
-        Event event = eventSerializer.fromJson(new String(eventAsBytes, StandardCharsets.UTF_8)).get();
         int currentRetryCount = getRetryCount(acknowledgableDelivery);
 
-        return delayGenerator.delayIfHaveTo(currentRetryCount)
-            .flatMap(any -> runListener(event))
-            .onErrorResume(throwable -> retryHandler.handleRetry(event, currentRetryCount, throwable))
-            .then(Mono.fromRunnable(acknowledgableDelivery::ack));
+        return deserializeEvent(eventAsBytes)
+            .flatMap(event -> delayGenerator.delayIfHaveTo(currentRetryCount)
+                .flatMap(any -> runListener(event))
+                .onErrorResume(throwable -> retryHandler.handleRetry(event, currentRetryCount, throwable))
+                .then(Mono.<Void>fromRunnable(acknowledgableDelivery::ack)))
+            .onErrorResume(e -> {
+                LOGGER.error("Unable to process delivery for group {}", group, e);
+                return Mono.fromRunnable(() -> acknowledgableDelivery.nack(!REQUEUE));
+            });
+    }
+
+    private Mono<Event> deserializeEvent(byte[] eventAsBytes) {
+        return Mono.fromCallable(() -> eventSerializer.fromJson(new String(eventAsBytes, StandardCharsets.UTF_8)).get())
+            .subscribeOn(Schedulers.parallel());
     }
 
     Mono<Void> reDeliver(Event event) {
diff --git a/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java b/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
index 9641df3..810187c 100644
--- a/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
+++ b/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
@@ -53,6 +53,7 @@ import java.io.Closeable;
 import java.nio.charset.StandardCharsets;
 import java.time.Duration;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.IntStream;
 import java.util.stream.Stream;
 
 import org.apache.james.backends.rabbitmq.RabbitMQExtension;
@@ -84,6 +85,7 @@ import com.google.common.collect.ImmutableSet;
 import reactor.core.publisher.Mono;
 import reactor.rabbitmq.BindingSpecification;
 import reactor.rabbitmq.ExchangeSpecification;
+import reactor.rabbitmq.OutboundMessage;
 import reactor.rabbitmq.QueueSpecification;
 import reactor.rabbitmq.Receiver;
 import reactor.rabbitmq.Sender;
@@ -172,6 +174,44 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
     }
 
     @Test
+    void eventProcessingShouldNotCrashOnInvalidMessage() {
+        EventCollector listener = new EventCollector();
+        EventBusTestFixture.GroupA registeredGroup = new EventBusTestFixture.GroupA();
+        eventBus.register(listener, registeredGroup);
+
+        String emptyRoutingKey = "";
+        rabbitMQExtension.getSender()
+            .send(Mono.just(new OutboundMessage(MAILBOX_EVENT_EXCHANGE_NAME,
+                emptyRoutingKey,
+                "BAD_PAYLOAD!".getBytes(StandardCharsets.UTF_8))))
+            .block();
+
+        eventBus.dispatch(EVENT, NO_KEYS).block();
+        await()
+            .timeout(org.awaitility.Duration.TEN_SECONDS).untilAsserted(() ->
+                assertThat(listener.getEvents()).containsOnly(EVENT));
+    }
+
+    @Test
+    void eventProcessingShouldNotCrashOnInvalidMessages() {
+        EventCollector listener = new EventCollector();
+        EventBusTestFixture.GroupA registeredGroup = new EventBusTestFixture.GroupA();
+        eventBus.register(listener, registeredGroup);
+
+        String emptyRoutingKey = "";
+        IntStream.range(0, 10).forEach(i -> rabbitMQExtension.getSender()
+            .send(Mono.just(new OutboundMessage(MAILBOX_EVENT_EXCHANGE_NAME,
+                emptyRoutingKey,
+                "BAD_PAYLOAD!".getBytes(StandardCharsets.UTF_8))))
+            .block());
+
+        eventBus.dispatch(EVENT, NO_KEYS).block();
+        await()
+            .timeout(org.awaitility.Duration.TEN_SECONDS).untilAsserted(() ->
+            assertThat(listener.getEvents()).containsOnly(EVENT));
+    }
+
+    @Test
     void deserializeEventCollectorGroup() throws Exception {
         assertThat(Group.deserialize("org.apache.james.mailbox.util.EventCollector$EventCollectorGroup"))
             .isEqualTo(new EventCollector.EventCollectorGroup());


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


[james-project] 03/09: JAMES-3305 Helper for RabbitMQ DeadLetter queue option

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit f0f598a754e0aac37ef1e77bede04506251adc8c
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Fri Jul 10 11:25:37 2020 +0700

    JAMES-3305 Helper for RabbitMQ DeadLetter queue option
---
 .../src/main/java/org/apache/james/backends/rabbitmq/Constants.java   | 4 ++++
 .../org/apache/james/queue/rabbitmq/RabbitMQMailQueueFactory.java     | 4 ++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/backends-common/rabbitmq/src/main/java/org/apache/james/backends/rabbitmq/Constants.java b/backends-common/rabbitmq/src/main/java/org/apache/james/backends/rabbitmq/Constants.java
index 021ab60..e415470 100644
--- a/backends-common/rabbitmq/src/main/java/org/apache/james/backends/rabbitmq/Constants.java
+++ b/backends-common/rabbitmq/src/main/java/org/apache/james/backends/rabbitmq/Constants.java
@@ -45,4 +45,8 @@ public interface Constants {
     AMQP.BasicProperties NO_PROPERTIES = new AMQP.BasicProperties();
 
     ImmutableMap<String, Object> NO_ARGUMENTS = ImmutableMap.of();
+
+    static ImmutableMap<String, Object> deadLetterQueue(String deadLetterQueueName) {
+        return ImmutableMap.of("x-dead-letter-exchange", deadLetterQueueName);
+    }
 }
diff --git a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueFactory.java b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueFactory.java
index 4dd0181..6d729ae 100644
--- a/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueFactory.java
+++ b/server/queue/queue-rabbitmq/src/main/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueFactory.java
@@ -24,6 +24,7 @@ import static org.apache.james.backends.rabbitmq.Constants.DURABLE;
 import static org.apache.james.backends.rabbitmq.Constants.EMPTY_ROUTING_KEY;
 import static org.apache.james.backends.rabbitmq.Constants.EXCLUSIVE;
 import static org.apache.james.backends.rabbitmq.Constants.NO_ARGUMENTS;
+import static org.apache.james.backends.rabbitmq.Constants.deadLetterQueue;
 import static org.apache.james.queue.api.MailQueue.QUEUE_SIZE_METRIC_NAME_PREFIX;
 
 import java.time.Clock;
@@ -46,7 +47,6 @@ import org.apache.james.queue.rabbitmq.view.RabbitMQMailQueueConfiguration;
 import org.apache.james.queue.rabbitmq.view.api.MailQueueView;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 
 import reactor.core.publisher.Flux;
@@ -164,7 +164,7 @@ public class RabbitMQMailQueueFactory implements MailQueueFactory<RabbitMQMailQu
                 .durable(DURABLE)
                 .exclusive(!EXCLUSIVE)
                 .autoDelete(!AUTO_DELETE)
-                .arguments(ImmutableMap.of("x-dead-letter-exchange", mailQueueName.toDeadLetterExchangeName()))),
+                .arguments(deadLetterQueue(mailQueueName.toDeadLetterExchangeName()))),
             sender.declareQueue(QueueSpecification.queue(mailQueueName.toDeadLetterQueueName())
                 .durable(DURABLE)
                 .exclusive(!EXCLUSIVE)


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


[james-project] 06/09: [Refactor] Remove unused misleading wrong configuration files

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit cbf90010efa1b1a0df0e34f58ef70aab51a6c307
Author: Raphael Ouazana <ra...@linagora.com>
AuthorDate: Thu Jul 9 10:22:14 2020 +0200

    [Refactor] Remove unused misleading wrong configuration files
---
 .../src/test/resources/usersrepository.xml         | 31 ----------------------
 .../src/test/resources/usersrepository.xml         | 31 ----------------------
 2 files changed, 62 deletions(-)

diff --git a/server/container/guice/cassandra-ldap-guice/src/test/resources/usersrepository.xml b/server/container/guice/cassandra-ldap-guice/src/test/resources/usersrepository.xml
deleted file mode 100644
index 6b94f9a..0000000
--- a/server/container/guice/cassandra-ldap-guice/src/test/resources/usersrepository.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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.                                           
- -->
-
-<!-- Read-Only LDAP based UsersRepository -->
-<usersrepository name="LocalUsers"
-                 ldapHost="ldap://myldapserver:389"
-                 principal="cn=admin,dc=james,dc=org"
-                 credentials="mysecretpassword"
-                 userBase="ou=People,dc=james,dc=org"
-                 userIdAttribute="uid"
-                 maxRetries="4"
-                 retryStartInterval="0"
-                 retryMaxInterval="8"
-                 retryIntervalScale="1000"/>
diff --git a/server/container/guice/cassandra-rabbitmq-ldap-guice/src/test/resources/usersrepository.xml b/server/container/guice/cassandra-rabbitmq-ldap-guice/src/test/resources/usersrepository.xml
deleted file mode 100644
index 6b94f9a..0000000
--- a/server/container/guice/cassandra-rabbitmq-ldap-guice/src/test/resources/usersrepository.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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.                                           
- -->
-
-<!-- Read-Only LDAP based UsersRepository -->
-<usersrepository name="LocalUsers"
-                 ldapHost="ldap://myldapserver:389"
-                 principal="cn=admin,dc=james,dc=org"
-                 credentials="mysecretpassword"
-                 userBase="ou=People,dc=james,dc=org"
-                 userIdAttribute="uid"
-                 maxRetries="4"
-                 retryStartInterval="0"
-                 retryMaxInterval="8"
-                 retryIntervalScale="1000"/>


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


[james-project] 01/09: JAMES-3295 Use MessageManager::listMessagesMetadata more widely

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 85ab0e3de59e6c1109495a1adf4b02fc5f912af4
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Sun Jul 12 21:25:52 2020 +0700

    JAMES-3295 Use MessageManager::listMessagesMetadata more widely
---
 .../imap/processor/AbstractMailboxProcessor.java   | 15 +++++++------
 .../james/imap/processor/SearchProcessor.java      | 11 +++++++---
 .../james/imap/processor/StoreProcessor.java       | 25 ++++++++++++++--------
 .../jmap/MessageFastViewProjectionCorrector.java   |  7 +++---
 4 files changed, 37 insertions(+), 21 deletions(-)

diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
index 0936cc6..4f23ebc 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
@@ -60,12 +60,10 @@ import org.apache.james.mailbox.ModSeq;
 import org.apache.james.mailbox.NullableMessageSequenceNumber;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MessageRangeException;
-import org.apache.james.mailbox.model.FetchGroup;
+import org.apache.james.mailbox.model.ComposedMessageIdWithMetaData;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.MessageRange.Type;
-import org.apache.james.mailbox.model.MessageResult;
-import org.apache.james.mailbox.model.MessageResultIterator;
 import org.apache.james.mailbox.model.SearchQuery;
 import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.metrics.api.TimeMetric;
@@ -74,6 +72,8 @@ import org.slf4j.LoggerFactory;
 
 import com.github.fge.lambdas.Throwing;
 
+import reactor.core.publisher.Flux;
+
 public abstract class AbstractMailboxProcessor<R extends ImapRequest> extends AbstractChainedProcessor<R> {
     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractMailboxProcessor.class);
 
@@ -242,12 +242,15 @@ public abstract class AbstractMailboxProcessor<R extends ImapRequest> extends Ab
                                    MessageRange messageSet, MessageManager mailbox,
                                    boolean isModSeqPermanent,
                                    MailboxSession mailboxSession) throws MailboxException {
-        final MessageResultIterator it = mailbox.getMessages(messageSet, FetchGroup.MINIMAL,  mailboxSession);
+        Iterator<ComposedMessageIdWithMetaData> it = Flux.from(
+            mailbox.listMessagesMetadata(messageSet, mailboxSession))
+            .toStream()
+            .iterator();
         final boolean qresyncEnabled = EnableProcessor.getEnabledCapabilities(session).contains(ImapConstants.SUPPORTS_QRESYNC);
         final boolean condstoreEnabled = EnableProcessor.getEnabledCapabilities(session).contains(ImapConstants.SUPPORTS_CONDSTORE);
         while (it.hasNext()) {
-            MessageResult mr = it.next();
-            final MessageUid uid = mr.getUid();
+            ComposedMessageIdWithMetaData mr = it.next();
+            final MessageUid uid = mr.getComposedMessageId().getUid();
             selected.msn(uid).fold(() -> {
                 LOGGER.debug("No message found with uid {} in the uid<->msn mapping for mailbox {}. This may be because it was deleted by a concurrent session. So skip it..", uid, selected.getMailboxId().serialize());
                 // skip this as it was not found in the mapping
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
index 58e6889..e86e850 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
@@ -23,6 +23,7 @@ import java.io.Closeable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Stream;
@@ -55,9 +56,8 @@ import org.apache.james.mailbox.MessageUid;
 import org.apache.james.mailbox.ModSeq;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MessageRangeException;
-import org.apache.james.mailbox.model.FetchGroup;
+import org.apache.james.mailbox.model.ComposedMessageIdWithMetaData;
 import org.apache.james.mailbox.model.MessageRange;
-import org.apache.james.mailbox.model.MessageResultIterator;
 import org.apache.james.mailbox.model.SearchQuery;
 import org.apache.james.mailbox.model.SearchQuery.AddressType;
 import org.apache.james.mailbox.model.SearchQuery.Criterion;
@@ -71,6 +71,8 @@ import com.github.fge.lambdas.Throwing;
 import com.github.steveash.guavate.Guavate;
 import com.google.common.collect.ImmutableList;
 
+import reactor.core.publisher.Flux;
+
 public class SearchProcessor extends AbstractMailboxProcessor<SearchRequest> implements CapabilityImplementingProcessor {
     private static final Logger LOGGER = LoggerFactory.getLogger(SearchProcessor.class);
 
@@ -248,7 +250,10 @@ public class SearchProcessor extends AbstractMailboxProcessor<SearchRequest> imp
         // Reverse loop over the ranges as its more likely that we find a match at the end
         int size = ranges.size();
         for (int i = size - 1; i > 0; i--) {
-            MessageResultIterator results = mailbox.getMessages(ranges.get(i), FetchGroup.MINIMAL, session);
+            Iterator<ComposedMessageIdWithMetaData> results = Flux.from(
+                mailbox.listMessagesMetadata(ranges.get(i), session))
+                .toStream()
+                .iterator();
             while (results.hasNext()) {
                 ModSeq modSeq = results.next().getModSeq();
                 if (highestModSeq == null || modSeq.asLong() > highestModSeq.asLong()) {
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
index f14fac2..0ec5697 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
@@ -23,6 +23,7 @@ import java.io.Closeable;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -52,16 +53,16 @@ import org.apache.james.mailbox.ModSeq;
 import org.apache.james.mailbox.NullableMessageSequenceNumber;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MessageRangeException;
-import org.apache.james.mailbox.model.FetchGroup;
+import org.apache.james.mailbox.model.ComposedMessageIdWithMetaData;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.MessageRange.Type;
-import org.apache.james.mailbox.model.MessageResult;
-import org.apache.james.mailbox.model.MessageResultIterator;
 import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.util.MDCBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import reactor.core.publisher.Flux;
+
 public class StoreProcessor extends AbstractMailboxProcessor<StoreRequest> {
     private static final Logger LOGGER = LoggerFactory.getLogger(StoreProcessor.class);
 
@@ -122,10 +123,13 @@ public class StoreProcessor extends AbstractMailboxProcessor<StoreRequest> {
                     if (unchangedSince != -1) {
                         List<MessageUid> uids = new ArrayList<>();
 
-                        MessageResultIterator results = mailbox.getMessages(messageSet, FetchGroup.MINIMAL, mailboxSession);
+                        Iterator<ComposedMessageIdWithMetaData> results = Flux.from(
+                            mailbox.listMessagesMetadata(messageSet, mailboxSession))
+                            .toStream()
+                            .iterator();
                         while (results.hasNext()) {
-                            MessageResult r = results.next();
-                            MessageUid uid = r.getUid();
+                            ComposedMessageIdWithMetaData r = results.next();
+                            MessageUid uid = r.getComposedMessageId().getUid();
 
                             boolean fail = false;
 
@@ -252,11 +256,14 @@ public class StoreProcessor extends AbstractMailboxProcessor<StoreRequest> {
             //      - QRESYNC was enabled via ENABLE QRESYNC
             //
             if (unchangedSince != -1 || qresyncEnabled || condstoreEnabled) {
-                MessageResultIterator results = mailbox.getMessages(messageSet, FetchGroup.MINIMAL, mailboxSession);
+                Iterator<ComposedMessageIdWithMetaData> results = Flux.from(
+                    mailbox.listMessagesMetadata(messageSet, mailboxSession))
+                    .toStream()
+                    .iterator();
                 while (results.hasNext()) {
-                    MessageResult r = results.next();
+                    ComposedMessageIdWithMetaData r = results.next();
                     // Store the modseq for the uid for later usage in the response
-                    modSeqs.put(r.getUid(),r.getModSeq());
+                    modSeqs.put(r.getComposedMessageId().getUid(),r.getModSeq());
                 }
             }
             
diff --git a/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/MessageFastViewProjectionCorrector.java b/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/MessageFastViewProjectionCorrector.java
index b54aaaf..7d37d04 100644
--- a/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/MessageFastViewProjectionCorrector.java
+++ b/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/MessageFastViewProjectionCorrector.java
@@ -34,6 +34,7 @@ import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageManager;
 import org.apache.james.mailbox.MessageUid;
 import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.ComposedMessageIdWithMetaData;
 import org.apache.james.mailbox.model.FetchGroup;
 import org.apache.james.mailbox.model.MailboxMetaData;
 import org.apache.james.mailbox.model.MessageId;
@@ -190,7 +191,7 @@ public class MessageFastViewProjectionCorrector {
         return listUsersMailboxes(session)
             .flatMap(mailboxMetadata -> retrieveMailbox(session, mailboxMetadata), MAILBOX_CONCURRENCY)
             .flatMap(Throwing.function(messageManager -> listAllMailboxMessages(messageManager, session)
-                .map(message -> new ProjectionEntry(messageManager, message.getUid(), session))), MAILBOX_CONCURRENCY)
+                .map(message -> new ProjectionEntry(messageManager, message.getComposedMessageId().getUid(), session))), MAILBOX_CONCURRENCY)
             .onErrorResume(MailboxException.class, e -> {
                 LOGGER.error("JMAP fastview re-computation aborted for {} as we failed listing user mailboxes", session.getUser(), e);
                 progress.incrementFailedUserCount();
@@ -231,8 +232,8 @@ public class MessageFastViewProjectionCorrector {
         return Mono.fromCallable(() -> mailboxManager.getMailbox(mailboxMetadata.getId(), session));
     }
 
-    private Flux<MessageResult> listAllMailboxMessages(MessageManager messageManager, MailboxSession session) throws MailboxException {
-        return Iterators.toFlux(messageManager.getMessages(MessageRange.all(), FetchGroup.MINIMAL, session));
+    private Flux<ComposedMessageIdWithMetaData> listAllMailboxMessages(MessageManager messageManager, MailboxSession session) {
+        return Flux.from(messageManager.listMessagesMetadata(MessageRange.all(), session));
     }
 
     private Mono<MessageResult> retrieveContent(MessageManager messageManager, MailboxSession session, MessageUid uid) {


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


[james-project] 09/09: JAMES-3266 Move disable ElasticSearch option into a separate search.properties configuration file

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c4fafaf7633afca1c995012a196a1b4ff3ed2ef0
Author: Raphael Ouazana <ra...@linagora.com>
AuthorDate: Wed Jul 8 17:37:59 2020 +0200

    JAMES-3266 Move disable ElasticSearch option into a separate search.properties configuration file
---
 .../java/org/apache/james/SearchConfiguration.java | 20 ++++---
 .../org/apache/james/SearchConfigurationTest.java  | 67 ++++++++++++++++++++++
 src/site/xdoc/server/config-elasticsearch.xml      |  4 +-
 3 files changed, 82 insertions(+), 9 deletions(-)

diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchConfiguration.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchConfiguration.java
index 9bc4f5c..0840e58 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchConfiguration.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchConfiguration.java
@@ -19,8 +19,6 @@
 
 package org.apache.james;
 
-import static org.apache.james.modules.mailbox.ElasticSearchMailboxModule.ELASTICSEARCH_CONFIGURATION_NAME;
-
 import java.io.FileNotFoundException;
 
 import org.apache.commons.configuration2.Configuration;
@@ -30,6 +28,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class SearchConfiguration {
+    public static final String SEARCH_CONFIGURATION_NAME = "search";
 
     public enum Implementation {
         Scanning,
@@ -38,19 +37,26 @@ public class SearchConfiguration {
 
     public static SearchConfiguration parse(PropertiesProvider propertiesProvider) throws ConfigurationException {
         try {
-            Configuration configuration = propertiesProvider.getConfiguration(ELASTICSEARCH_CONFIGURATION_NAME);
+            Configuration configuration = propertiesProvider.getConfiguration(SEARCH_CONFIGURATION_NAME);
             return SearchConfiguration.from(configuration);
         } catch (FileNotFoundException e) {
-            LOGGER.warn("Could not find {} configuration file, enabling elasticsearch by default", ELASTICSEARCH_CONFIGURATION_NAME);
+            LOGGER.debug("Could not find {} configuration file, enabling elasticsearch by default", SEARCH_CONFIGURATION_NAME);
             return elasticSearch();
         }
     }
 
-    static SearchConfiguration from(Configuration configuration) {
-        if (configuration.getBoolean("enabled", true)) {
+    static SearchConfiguration from(Configuration configuration) throws ConfigurationException {
+        String searchOption = configuration.getString("implementation", Implementation.ElasticSearch.name());
+        if (searchOption.equalsIgnoreCase(Implementation.ElasticSearch.name())) {
             return elasticSearch();
         }
-        return scanning();
+        if (searchOption.equalsIgnoreCase(Implementation.Scanning.name())) {
+            return scanning();
+        }
+        throw new ConfigurationException(String.format("'implementation' parameter in '%s.properties' should have '%s' or '%s' value",
+                SEARCH_CONFIGURATION_NAME,
+                Implementation.ElasticSearch.name(),
+                Implementation.Scanning.name()));
     }
 
     public static SearchConfiguration scanning() {
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/SearchConfigurationTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/SearchConfigurationTest.java
new file mode 100644
index 0000000..ecb0a62
--- /dev/null
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/SearchConfigurationTest.java
@@ -0,0 +1,67 @@
+/****************************************************************
+ * 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;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.apache.commons.configuration2.PropertiesConfiguration;
+import org.apache.commons.configuration2.ex.ConfigurationException;
+import org.junit.jupiter.api.Test;
+
+class SearchConfigurationTest {
+    @Test
+    void unknownSearchImplementationShouldThrow() {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty("implementation", "unknown");
+        assertThatThrownBy(() -> SearchConfiguration.from(configuration))
+            .isInstanceOf(ConfigurationException.class);
+    }
+
+    @Test
+    void searchImplementationShouldReturnElasticSearchByDefault() throws Exception {
+        assertThat(SearchConfiguration.from(new PropertiesConfiguration()).getImplementation())
+            .isEqualTo(SearchConfiguration.Implementation.ElasticSearch);
+    }
+
+    @Test
+    void searchImplementationShouldReturnElasticSearchWhenSetToElasticSearch() throws Exception {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty("implementation", "ElasticSearch");
+        assertThat(SearchConfiguration.from(configuration).getImplementation())
+                .isEqualTo(SearchConfiguration.Implementation.ElasticSearch);
+    }
+
+    @Test
+    void searchImplementationShouldReturnElasticSearchWhenSetToElasticSearchWithAlternativeCase() throws Exception {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty("implementation", "elasticsearch");
+        assertThat(SearchConfiguration.from(configuration).getImplementation())
+                .isEqualTo(SearchConfiguration.Implementation.ElasticSearch);
+    }
+
+    @Test
+    void searchImplementationShouldReturnScanningSearchWhenSetToScanningSearch() throws Exception {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty("implementation", "scanning");
+        assertThat(SearchConfiguration.from(configuration).getImplementation())
+                .isEqualTo(SearchConfiguration.Implementation.Scanning);
+    }
+}
diff --git a/src/site/xdoc/server/config-elasticsearch.xml b/src/site/xdoc/server/config-elasticsearch.xml
index 866f887..ed085de 100644
--- a/src/site/xdoc/server/config-elasticsearch.xml
+++ b/src/site/xdoc/server/config-elasticsearch.xml
@@ -117,8 +117,8 @@
 
       <p>
           ElasticSearch component can be disabled but consider it would make search feature to not work. In particular it will break JMAP protocol and SEARCH IMAP comment in an nondeterministic way.
-          This is controlled via the <code>enabled</code> property (boolean, defaults
-          to true). Setting this configuration parameter to <code>false</code> will effectively disable ElasticSearch, no
+          This is controlled in the <code>search.properties</code> file via the <code>implementation</code> property (defaults
+          to <code>ElasticSearch</code>). Setting this configuration parameter to <code>scanning</code> will effectively disable ElasticSearch, no
           further indexation will be done however searches will rely on the scrolling search, leading to expensive and longer
           searches. Disabling ElasticSearch requires no extra action, however
           <a href="https://github.com/apache/james-project/blob/master/src/site/markdown/server/manage-webadmin.md#reindexing-all-mails">


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


[james-project] 08/09: JAMES-3266 Document ElasticSearch opt-in/opt-out

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 106bba2e9e753b7d8954695fe12e20e4f7ef07b0
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Tue Jun 23 17:24:42 2020 +0700

    JAMES-3266 Document ElasticSearch opt-in/opt-out
---
 .../java/org/apache/james/SearchModuleChooser.java | 11 ++------
 .../AuthenticatedCassandraJamesServerTest.java     | 21 ++------------
 .../org/apache/james/CassandraJamesServerTest.java |  7 +----
 .../apache/james/CassandraJmapJamesServerTest.java |  7 +----
 .../CassandraMailRepositoryIntegrationTest.java    |  7 +----
 .../CassandraMessageIdManagerInjectionTest.java    |  7 +----
 .../org/apache/james/CassandraNodeConfTest.java    |  7 +----
 .../org/apache/james/CassandraWithTikaTest.java    |  8 +-----
 .../james/DefaultCassandraJamesServerTest.java     |  7 +----
 .../test/java/org/apache/james/ESReporterTest.java |  7 +----
 .../apache/james/JamesCapabilitiesServerTest.java  |  7 +----
 .../james/JamesServerWithRetryConnectionTest.java  |  7 +----
 ...esWithNonCompatibleElasticSearchServerTest.java |  7 +----
 .../org/apache/james/KeyspaceCreationTest.java     | 28 +++----------------
 ...a => TestingDistributedJamesServerBuilder.java} | 32 ++++++++++------------
 .../apache/james/WithCassandraBlobStoreTest.java   |  7 +----
 .../apache/james/CassandraLdapJamesServerTest.java |  7 +----
 .../james/CassandraLdapJmapJamesServerTest.java    |  7 +----
 .../jmap/cassandra/CassandraImapErrorTest.java     | 10 ++-----
 .../jmap/cassandra/CassandraSendMDNMethodTest.java | 10 ++-----
 .../CassandraSpamAssassinContractTest.java         | 10 ++-----
 src/site/xdoc/server/config-elasticsearch.xml      | 10 +++++++
 22 files changed, 55 insertions(+), 176 deletions(-)

diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchModuleChooser.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchModuleChooser.java
index b6713f3..a35b5d9 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchModuleChooser.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchModuleChooser.java
@@ -66,11 +66,6 @@ public class SearchModuleChooser {
 
     // Required for CLI
     private static class FakeMessageSearchIndex extends ListeningMessageSearchIndex {
-        private static class FakeMessageSearchIndexGroup extends Group {
-
-        }
-
-        private static final FakeMessageSearchIndexGroup GROUP = new FakeMessageSearchIndexGroup();
 
         public FakeMessageSearchIndex() {
             super(null, null);
@@ -82,7 +77,7 @@ public class SearchModuleChooser {
         }
 
         @Override
-        public Mono<Void> delete(MailboxSession session, Mailbox mailbox, Collection<MessageUid> expungedUids) {
+        public Mono<Void> delete(MailboxSession session, MailboxId mailboxId, Collection<MessageUid> expungedUids) {
             throw new NotImplementedException("not implemented");
         }
 
@@ -92,7 +87,7 @@ public class SearchModuleChooser {
         }
 
         @Override
-        public Mono<Void> update(MailboxSession session, Mailbox mailbox, List<UpdatedFlags> updatedFlagsList) {
+        public Mono<Void> update(MailboxSession session, MailboxId mailboxId, List<UpdatedFlags> updatedFlagsList) {
             throw new NotImplementedException("not implemented");
         }
 
@@ -103,7 +98,7 @@ public class SearchModuleChooser {
 
         @Override
         public Group getDefaultGroup() {
-            return GROUP;
+            throw new NotImplementedException("not implemented");
         }
 
         @Override
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java
index 9a5fd68..58a6b35 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java
@@ -43,12 +43,7 @@ class AuthenticatedCassandraJamesServerTest {
     @Nested
     class AuthenticationTest implements JamesServerContract {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-            CassandraJamesServerConfiguration.builder()
-                .workingDirectory(tmpDir)
-                .configurationFromClasspath()
-                .searchConfiguration(SearchConfiguration.elasticSearch())
-                .build())
+        JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
             .extension(new DockerElasticSearchExtension())
             .extension(cassandraExtension)
             .server(configuration -> CassandraJamesServerMain.createServer(configuration)
@@ -64,12 +59,7 @@ class AuthenticatedCassandraJamesServerTest {
     @Nested
     class SslTest {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-            CassandraJamesServerConfiguration.builder()
-                .workingDirectory(tmpDir)
-                .configurationFromClasspath()
-                .searchConfiguration(SearchConfiguration.elasticSearch())
-                .build())
+        JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
             .extension(new DockerElasticSearchExtension())
             .extension(cassandraExtension)
             .disableAutoStart()
@@ -94,12 +84,7 @@ class AuthenticatedCassandraJamesServerTest {
     @Nested
     class AuthenticationFailureTest {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-            CassandraJamesServerConfiguration.builder()
-                .workingDirectory(tmpDir)
-                .configurationFromClasspath()
-                .searchConfiguration(SearchConfiguration.elasticSearch())
-                .build())
+        JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
             .extension(new DockerElasticSearchExtension())
             .extension(cassandraExtension)
             .disableAutoStart()
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJamesServerTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJamesServerTest.java
index cab7b20..699ca01 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJamesServerTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJamesServerTest.java
@@ -30,12 +30,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraJamesServerTest implements JamesServerContract {
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    static JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapJamesServerTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapJamesServerTest.java
index 69fe6a7..97efb6b 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapJamesServerTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapJamesServerTest.java
@@ -27,12 +27,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraJmapJamesServerTest implements JmapJamesServerContract {
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    static JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMailRepositoryIntegrationTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMailRepositoryIntegrationTest.java
index 88f0c7b..77354ac 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMailRepositoryIntegrationTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMailRepositoryIntegrationTest.java
@@ -47,12 +47,7 @@ class CassandraMailRepositoryIntegrationTest {
     private SMTPMessageSender smtpMessageSender = new SMTPMessageSender("other.com");
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    static JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMessageIdManagerInjectionTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMessageIdManagerInjectionTest.java
index 49378ba..3ea1bd9 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMessageIdManagerInjectionTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMessageIdManagerInjectionTest.java
@@ -33,12 +33,7 @@ import com.google.inject.multibindings.Multibinder;
 
 class CassandraMessageIdManagerInjectionTest {
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    static JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java
index b9bd416..738e50b 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java
@@ -42,12 +42,7 @@ class CassandraNodeConfTest {
     private static final int CASSANDRA_PORT = 9042;
 
     private static JamesServerBuilder extensionBuilder() {
-        return new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-            CassandraJamesServerConfiguration.builder()
-                .workingDirectory(tmpDir)
-                .configurationFromClasspath()
-                .searchConfiguration(SearchConfiguration.elasticSearch())
-                .build())
+        return TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
             .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraWithTikaTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraWithTikaTest.java
index db503ed..31615a3 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraWithTikaTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraWithTikaTest.java
@@ -24,13 +24,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraWithTikaTest implements JamesServerContract {
     @RegisterExtension
-    static JamesServerExtension testExtension =
-        new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-            CassandraJamesServerConfiguration.builder()
-                .workingDirectory(tmpDir)
-                .configurationFromClasspath()
-                .searchConfiguration(SearchConfiguration.elasticSearch())
-                .build())
+    static JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
             .extension(new CassandraExtension())
             .extension(new  TikaExtension())
             .extension(new DockerElasticSearchExtension())
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DefaultCassandraJamesServerTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DefaultCassandraJamesServerTest.java
index 7bca678..86b6de5 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DefaultCassandraJamesServerTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DefaultCassandraJamesServerTest.java
@@ -33,12 +33,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 
 class DefaultCassandraJamesServerTest {
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    static JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/ESReporterTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/ESReporterTest.java
index 50a1fd4..f3a12db 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/ESReporterTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/ESReporterTest.java
@@ -61,12 +61,7 @@ class ESReporterTest {
     static final DockerElasticSearchExtension elasticSearchExtension = new DockerElasticSearchExtension();
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    static JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(elasticSearchExtension)
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesCapabilitiesServerTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesCapabilitiesServerTest.java
index 12fd2a1..0a8f58d 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesCapabilitiesServerTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesCapabilitiesServerTest.java
@@ -36,12 +36,7 @@ class JamesCapabilitiesServerTest {
     private static final MailboxManager mailboxManager = mock(MailboxManager.class);
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    static JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesServerWithRetryConnectionTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesServerWithRetryConnectionTest.java
index 387c2fc..8afe525 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesServerWithRetryConnectionTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesServerWithRetryConnectionTest.java
@@ -46,12 +46,7 @@ class JamesServerWithRetryConnectionTest {
     private static final CassandraExtension dockerCassandra = new CassandraExtension();
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    static JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(dockerElasticSearch)
         .extension(dockerCassandra)
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesWithNonCompatibleElasticSearchServerTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesWithNonCompatibleElasticSearchServerTest.java
index e6021a2..8dded5f 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesWithNonCompatibleElasticSearchServerTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesWithNonCompatibleElasticSearchServerTest.java
@@ -37,12 +37,7 @@ class JamesWithNonCompatibleElasticSearchServerTest {
     static DockerElasticSearch dockerES2 = new DockerElasticSearch.NoAuth(Images.ELASTICSEARCH_2);
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    static JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(new DockerElasticSearchExtension(dockerES2))
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/KeyspaceCreationTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/KeyspaceCreationTest.java
index 8adcc62..14e229e 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/KeyspaceCreationTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/KeyspaceCreationTest.java
@@ -33,12 +33,7 @@ class KeyspaceCreationTest {
     @Nested
     class CreateWhenKeyspaceExists {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+        JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
             .server(CassandraJamesServerMain::createServer)
@@ -59,12 +54,7 @@ class KeyspaceCreationTest {
     @Nested
     class CreateWhenDoesNotExistAndHasRights {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+        JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
             .server(CassandraJamesServerMain::createServer)
@@ -91,12 +81,7 @@ class KeyspaceCreationTest {
     @Nested
     class CreateWhenDoesNotExistAndDoNotHaveRights {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+        JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
             .server(CassandraJamesServerMain::createServer)
@@ -123,12 +108,7 @@ class KeyspaceCreationTest {
     @Nested
     class StartWhenKeyspaceDoesNotExist {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+        JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
             .server(CassandraJamesServerMain::createServer)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraWithTikaTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/TestingDistributedJamesServerBuilder.java
similarity index 58%
copy from server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraWithTikaTest.java
copy to server/container/guice/cassandra-guice/src/test/java/org/apache/james/TestingDistributedJamesServerBuilder.java
index db503ed..211ef78 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraWithTikaTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/TestingDistributedJamesServerBuilder.java
@@ -19,23 +19,21 @@
 
 package org.apache.james;
 
-import org.apache.james.modules.TestJMAPServerModule;
-import org.junit.jupiter.api.extension.RegisterExtension;
+public class TestingDistributedJamesServerBuilder {
+    @FunctionalInterface
+    interface ConfigurationSpecification {
+        CassandraJamesServerConfiguration.Builder customize(CassandraJamesServerConfiguration.Builder configuration);
+    }
 
-class CassandraWithTikaTest implements JamesServerContract {
-    @RegisterExtension
-    static JamesServerExtension testExtension =
-        new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-            CassandraJamesServerConfiguration.builder()
+    public static JamesServerBuilder<CassandraJamesServerConfiguration> forConfiguration(ConfigurationSpecification configurationSpecification) {
+        return new JamesServerBuilder<>(tmpDir ->
+            configurationSpecification.customize(CassandraJamesServerConfiguration.builder()
                 .workingDirectory(tmpDir)
-                .configurationFromClasspath()
-                .searchConfiguration(SearchConfiguration.elasticSearch())
-                .build())
-            .extension(new CassandraExtension())
-            .extension(new  TikaExtension())
-            .extension(new DockerElasticSearchExtension())
-            .server(configuration -> CassandraJamesServerMain.createServer(configuration)
-                .overrideWith(new TestJMAPServerModule())
-                .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE))
-            .build();
+                .configurationFromClasspath())
+                .build());
+    }
+
+    public static JamesServerBuilder<CassandraJamesServerConfiguration> withSearchConfiguration(SearchConfiguration searchConfiguration) {
+        return forConfiguration(configuration -> configuration.searchConfiguration(searchConfiguration));
+    }
 }
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/WithCassandraBlobStoreTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/WithCassandraBlobStoreTest.java
index c86d4d8..d8f99b4 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/WithCassandraBlobStoreTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/WithCassandraBlobStoreTest.java
@@ -27,12 +27,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 class WithCassandraBlobStoreTest implements JmapJamesServerContract, MailsShouldBeWellReceived, JamesServerContract {
 
     @RegisterExtension
-    static JamesServerExtension jamesServerExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    static JamesServerExtension jamesServerExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .extension(new SpamAssassinModuleExtension())
diff --git a/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJamesServerTest.java b/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJamesServerTest.java
index 8c20b54..7d5e782 100644
--- a/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJamesServerTest.java
+++ b/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJamesServerTest.java
@@ -53,12 +53,7 @@ class CassandraLdapJamesServerTest implements JamesServerContract {
     SMTPMessageSender messageSender = new SMTPMessageSender(Domain.LOCALHOST.asString());
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    static JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .extension(new LdapTestExtension())
diff --git a/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJmapJamesServerTest.java b/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJmapJamesServerTest.java
index ccf7097..7c537b0 100644
--- a/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJmapJamesServerTest.java
+++ b/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJmapJamesServerTest.java
@@ -25,12 +25,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraLdapJmapJamesServerTest implements JmapJamesServerContract {
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    static JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .extension(new LdapTestExtension())
diff --git a/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraImapErrorTest.java b/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraImapErrorTest.java
index e4261ab..7a5119e 100644
--- a/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraImapErrorTest.java
+++ b/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraImapErrorTest.java
@@ -26,13 +26,12 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 import org.apache.commons.net.imap.IMAPClient;
 import org.apache.james.CassandraExtension;
-import org.apache.james.CassandraJamesServerConfiguration;
 import org.apache.james.CassandraJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.GuiceJamesServer;
-import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
 import org.apache.james.SearchConfiguration;
+import org.apache.james.TestingDistributedJamesServerBuilder;
 import org.apache.james.jmap.draft.JmapGuiceProbe;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.apache.james.modules.protocols.ImapGuiceProbe;
@@ -49,12 +48,7 @@ class CassandraImapErrorTest {
     private final CassandraExtension cassandraExtension = new CassandraExtension();
 
     @RegisterExtension
-    JamesServerExtension serverExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    JamesServerExtension serverExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(new DockerElasticSearchExtension())
         .extension(cassandraExtension)
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSendMDNMethodTest.java b/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSendMDNMethodTest.java
index 1a171d3..54bd376 100644
--- a/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSendMDNMethodTest.java
+++ b/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSendMDNMethodTest.java
@@ -20,12 +20,11 @@
 package org.apache.james.jmap.cassandra;
 
 import org.apache.james.CassandraExtension;
-import org.apache.james.CassandraJamesServerConfiguration;
 import org.apache.james.CassandraJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
-import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
 import org.apache.james.SearchConfiguration;
+import org.apache.james.TestingDistributedJamesServerBuilder;
 import org.apache.james.jmap.draft.methods.integration.SendMDNMethodTest;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.model.MessageId;
@@ -35,12 +34,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 public class CassandraSendMDNMethodTest extends SendMDNMethodTest {
 
     @RegisterExtension
-    JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSpamAssassinContractTest.java b/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSpamAssassinContractTest.java
index c06f44b..5ad8098 100644
--- a/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSpamAssassinContractTest.java
+++ b/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSpamAssassinContractTest.java
@@ -19,12 +19,11 @@
 package org.apache.james.jmap.cassandra;
 
 import org.apache.james.CassandraExtension;
-import org.apache.james.CassandraJamesServerConfiguration;
 import org.apache.james.CassandraJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
-import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
 import org.apache.james.SearchConfiguration;
+import org.apache.james.TestingDistributedJamesServerBuilder;
 import org.apache.james.jmap.draft.methods.integration.SpamAssassinContract;
 import org.apache.james.jmap.draft.methods.integration.SpamAssassinModuleExtension;
 import org.apache.james.modules.TestJMAPServerModule;
@@ -35,12 +34,7 @@ class CassandraSpamAssassinContractTest implements SpamAssassinContract {
     private static final SpamAssassinModuleExtension spamAssassinExtension = new SpamAssassinModuleExtension();
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
-        CassandraJamesServerConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
+    static JamesServerExtension testExtension = TestingDistributedJamesServerBuilder.withSearchConfiguration(SearchConfiguration.elasticSearch())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .extension(spamAssassinExtension)
diff --git a/src/site/xdoc/server/config-elasticsearch.xml b/src/site/xdoc/server/config-elasticsearch.xml
index 3a6f54e..866f887 100644
--- a/src/site/xdoc/server/config-elasticsearch.xml
+++ b/src/site/xdoc/server/config-elasticsearch.xml
@@ -115,6 +115,16 @@
           <dd>Specify the ElasticSearch alias name used for writing quotas</dd>
       </dl>
 
+      <p>
+          ElasticSearch component can be disabled but consider it would make search feature to not work. In particular it will break JMAP protocol and SEARCH IMAP comment in an nondeterministic way.
+          This is controlled via the <code>enabled</code> property (boolean, defaults
+          to true). Setting this configuration parameter to <code>false</code> will effectively disable ElasticSearch, no
+          further indexation will be done however searches will rely on the scrolling search, leading to expensive and longer
+          searches. Disabling ElasticSearch requires no extra action, however
+          <a href="https://github.com/apache/james-project/blob/master/src/site/markdown/server/manage-webadmin.md#reindexing-all-mails">
+              a full re-indexing</a> needs to be carried out when enabling ElasticSearch.
+      </p>
+
       For configuring the metric reporting on ElasticSearch :
 
       <dl>


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


[james-project] 07/09: JAMES-3266 Offer an option to disable ElasticSearch in Distributed James product

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 88ba42685d811760044bd21c1dcdf4ede7837745
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Jun 4 11:22:56 2020 +0700

    JAMES-3266 Offer an option to disable ElasticSearch in Distributed James product
---
 server/container/guice/cassandra-guice/pom.xml     |   4 +
 .../james/CassandraJamesServerConfiguration.java}  |  36 +++--
 .../org/apache/james/CassandraJamesServerMain.java |  16 +--
 .../java/org/apache/james/SearchConfiguration.java |  76 ++++++++++
 .../java/org/apache/james/SearchModuleChooser.java | 154 +++++++++++++++++++++
 .../AuthenticatedCassandraJamesServerTest.java     |  21 ++-
 .../java/org/apache/james/CacheSessionTest.java    |   7 +-
 .../org/apache/james/CassandraJamesServerTest.java |   7 +-
 .../apache/james/CassandraJmapJamesServerTest.java |   7 +-
 .../org/apache/james/CassandraJmapTestRule.java    |   4 +-
 .../CassandraMailRepositoryIntegrationTest.java    |   7 +-
 .../CassandraMessageIdManagerInjectionTest.java    |   7 +-
 .../org/apache/james/CassandraNodeConfTest.java    |   7 +-
 .../org/apache/james/CassandraWithTikaTest.java    |   7 +-
 .../james/DefaultCassandraJamesServerTest.java     |   7 +-
 .../test/java/org/apache/james/ESReporterTest.java |   7 +-
 .../apache/james/JamesCapabilitiesServerTest.java  |   7 +-
 .../james/JamesServerWithRetryConnectionTest.java  |   7 +-
 ...esWithNonCompatibleElasticSearchServerTest.java |   7 +-
 .../org/apache/james/KeyspaceCreationTest.java     |  28 +++-
 .../apache/james/WithCassandraBlobStoreTest.java   |   7 +-
 .../CassandraSchemaVersionStartUpCheckTest.java    |   9 +-
 .../apache/james/CassandraLdapJamesServerMain.java |   8 +-
 .../apache/james/CassandraLdapJamesServerTest.java |   7 +-
 .../james/CassandraLdapJmapJamesServerTest.java    |   7 +-
 .../james/CassandraRabbitMQJamesConfiguration.java |  28 +++-
 .../james/CassandraRabbitMQJamesServerMain.java    |   4 +-
 .../james/CassandraRabbitMQAwsS3JmapTestRule.java  |   1 +
 .../james/CassandraRabbitMQJamesServerFixture.java |   1 +
 .../james/CassandraRabbitMQSwiftJmapTestRule.java  |   1 +
 .../java/org/apache/james/WithCacheExtension.java  |   1 +
 .../org/apache/james/WithCassandraBlobStore.java   |   1 +
 ...nsion.java => WithScanningSearchExtension.java} |   8 +-
 .../org/apache/james/WithScanningSearchTest.java}  |  19 +--
 .../CassandraRabbitMQLdapJamesServerMain.java      |   6 +-
 .../CassandraRabbitMQLdapJmapJamesServerTest.java  |   1 +
 .../jmap/cassandra/CassandraImapErrorTest.java     |   9 +-
 .../jmap/cassandra/CassandraSendMDNMethodTest.java |   9 +-
 .../CassandraSpamAssassinContractTest.java         |   9 +-
 .../jmap/cassandra/cucumber/CassandraStepdefs.java |   6 +-
 .../rabbitmq/RabbitMQAwsS3SendMDNMethodTest.java   |   2 +
 .../RabbitMQAwsS3SpamAssassinContractTest.java     |   2 +
 .../cucumber/awss3/RabbitMQAwsS3Stepdefs.java      |   2 +
 .../distributed/DistributedAuthenticationTest.java |   2 +
 .../distributed/DistributedEchoMethodTest.java     |   2 +
 .../rabbitmq/ConsistencyTasksIntegrationTest.java  |   2 +
 .../rabbitmq/FixingGhostMailboxTest.java           |   2 +
 .../rabbitmq/RabbitMQAuthorizedEndpointsTest.java  |   2 +
 .../RabbitMQEventDeadLettersIntegrationTest.java   |   2 +
 ...stViewProjectionHealthCheckIntegrationTest.java |   2 +
 .../rabbitmq/RabbitMQForwardIntegrationTest.java   |   2 +
 .../rabbitmq/RabbitMQJmapExtension.java            |   2 +
 .../rabbitmq/RabbitMQJwtFilterIntegrationTest.java |   2 +
 ...RabbitMQReindexingWithEventDeadLettersTest.java |   2 +
 .../RabbitMQWebAdminServerIntegrationTest.java     |   2 +
 ...dminServerTaskSerializationIntegrationTest.java |   2 +
 ...RabbitMQDeletedMessageVaultIntegrationTest.java |   2 +
 ...LinshareBlobExportMechanismIntegrationTest.java |   2 +
 58 files changed, 512 insertions(+), 89 deletions(-)

diff --git a/server/container/guice/cassandra-guice/pom.xml b/server/container/guice/cassandra-guice/pom.xml
index 8526e09..01c7a62 100644
--- a/server/container/guice/cassandra-guice/pom.xml
+++ b/server/container/guice/cassandra-guice/pom.xml
@@ -95,6 +95,10 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>apache-james-mailbox-quota-search-scanning</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>apache-james-mailbox-tika</artifactId>
             <type>test-jar</type>
             <scope>test</scope>
diff --git a/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/CassandraRabbitMQJamesConfiguration.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerConfiguration.java
similarity index 74%
copy from server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/CassandraRabbitMQJamesConfiguration.java
copy to server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerConfiguration.java
index 83c2b7e..30478c0 100644
--- a/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/CassandraRabbitMQJamesConfiguration.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerConfiguration.java
@@ -24,7 +24,6 @@ import java.util.Optional;
 
 import org.apache.james.filesystem.api.FileSystem;
 import org.apache.james.filesystem.api.JamesDirectoriesProvider;
-import org.apache.james.modules.blobstore.BlobStoreConfiguration;
 import org.apache.james.server.core.JamesServerResourceLoader;
 import org.apache.james.server.core.MissingArgumentException;
 import org.apache.james.server.core.configuration.Configuration;
@@ -33,16 +32,16 @@ import org.apache.james.utils.PropertiesProvider;
 
 import com.github.fge.lambdas.Throwing;
 
-public class CassandraRabbitMQJamesConfiguration implements Configuration {
+public class CassandraJamesServerConfiguration implements Configuration {
     public static class Builder {
-        private Optional<BlobStoreConfiguration> blobStoreConfiguration;
+        private Optional<SearchConfiguration> searchConfiguration;
         private Optional<String> rootDirectory;
         private Optional<ConfigurationPath> configurationPath;
 
         private Builder() {
             rootDirectory = Optional.empty();
             configurationPath = Optional.empty();
-            blobStoreConfiguration = Optional.empty();
+            searchConfiguration = Optional.empty();
         }
 
         public Builder workingDirectory(String path) {
@@ -73,37 +72,36 @@ public class CassandraRabbitMQJamesConfiguration implements Configuration {
             return this;
         }
 
-        public Builder blobStore(BlobStoreConfiguration blobStoreConfiguration) {
-            this.blobStoreConfiguration = Optional.of(blobStoreConfiguration);
+        public Builder searchConfiguration(SearchConfiguration searchConfiguration) {
+            this.searchConfiguration = Optional.of(searchConfiguration);
             return this;
         }
 
-        public CassandraRabbitMQJamesConfiguration build() {
+        public CassandraJamesServerConfiguration build() {
             ConfigurationPath configurationPath = this.configurationPath.orElse(new ConfigurationPath(FileSystem.FILE_PROTOCOL_AND_CONF));
             JamesServerResourceLoader directories = new JamesServerResourceLoader(rootDirectory
                 .orElseThrow(() -> new MissingArgumentException("Server needs a working.directory env entry")));
 
-            return new CassandraRabbitMQJamesConfiguration(
-                configurationPath,
-                directories,
-                blobStoreConfiguration.orElseGet(Throwing.supplier(
-                    () -> BlobStoreConfiguration.parse(
-                        new PropertiesProvider(new FileSystemImpl(directories), configurationPath)))));
+            SearchConfiguration searchConfiguration = this.searchConfiguration.orElseGet(Throwing.supplier(
+                () -> SearchConfiguration.parse(
+                    new PropertiesProvider(new FileSystemImpl(directories), configurationPath))));
+
+            return new CassandraJamesServerConfiguration(configurationPath, directories, searchConfiguration);
         }
     }
 
-    public static CassandraRabbitMQJamesConfiguration.Builder builder() {
+    public static CassandraJamesServerConfiguration.Builder builder() {
         return new Builder();
     }
 
     private final ConfigurationPath configurationPath;
     private final JamesDirectoriesProvider directories;
-    private final BlobStoreConfiguration blobStoreConfiguration;
+    private final SearchConfiguration searchConfiguration;
 
-    public CassandraRabbitMQJamesConfiguration(ConfigurationPath configurationPath, JamesDirectoriesProvider directories, BlobStoreConfiguration blobStoreConfiguration) {
+    private CassandraJamesServerConfiguration(ConfigurationPath configurationPath, JamesDirectoriesProvider directories, SearchConfiguration searchConfiguration) {
         this.configurationPath = configurationPath;
         this.directories = directories;
-        this.blobStoreConfiguration = blobStoreConfiguration;
+        this.searchConfiguration = searchConfiguration;
     }
 
     @Override
@@ -116,7 +114,7 @@ public class CassandraRabbitMQJamesConfiguration implements Configuration {
         return directories;
     }
 
-    public BlobStoreConfiguration blobStoreConfiguration() {
-        return blobStoreConfiguration;
+    public SearchConfiguration searchConfiguration() {
+        return searchConfiguration;
     }
 }
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java
index bef678e..934538e 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java
@@ -42,8 +42,6 @@ import org.apache.james.modules.mailbox.CassandraDeletedMessageVaultModule;
 import org.apache.james.modules.mailbox.CassandraMailboxModule;
 import org.apache.james.modules.mailbox.CassandraQuotaMailingModule;
 import org.apache.james.modules.mailbox.CassandraSessionModule;
-import org.apache.james.modules.mailbox.ElasticSearchClientModule;
-import org.apache.james.modules.mailbox.ElasticSearchMailboxModule;
 import org.apache.james.modules.mailbox.TikaMailboxModule;
 import org.apache.james.modules.metrics.CassandraMetricsModule;
 import org.apache.james.modules.protocols.IMAPServerModule;
@@ -65,7 +63,6 @@ import org.apache.james.modules.server.MailRepositoriesRoutesModule;
 import org.apache.james.modules.server.MailboxRoutesModule;
 import org.apache.james.modules.server.MailboxesExportRoutesModule;
 import org.apache.james.modules.server.MessagesRoutesModule;
-import org.apache.james.modules.server.ReIndexingModule;
 import org.apache.james.modules.server.SieveRoutesModule;
 import org.apache.james.modules.server.SwaggerRoutesModule;
 import org.apache.james.modules.server.TaskManagerModule;
@@ -75,7 +72,6 @@ import org.apache.james.modules.spamassassin.SpamAssassinListenerModule;
 import org.apache.james.modules.vault.DeletedMessageVaultRoutesModule;
 import org.apache.james.modules.webadmin.CassandraRoutesModule;
 import org.apache.james.modules.webadmin.InconsistencySolvingRoutesModule;
-import org.apache.james.server.core.configuration.Configuration;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.inject.Module;
@@ -97,7 +93,6 @@ public class CassandraJamesServerMain implements JamesServerMain {
         new MailboxRoutesModule(),
         new MailQueueRoutesModule(),
         new MailRepositoriesRoutesModule(),
-        new ReIndexingModule(),
         new SieveRoutesModule(),
         new SwaggerRoutesModule(),
         new WebAdminServerModule(),
@@ -138,6 +133,7 @@ public class CassandraJamesServerMain implements JamesServerMain {
         new CassandraSessionModule(),
         new CassandraSieveRepositoryModule(),
         new CassandraUsersRepositoryModule(),
+        new ElasticSearchMetricReporterModule(),
         BLOB_MODULE,
         CASSANDRA_EVENT_STORE_JSON_SERIALIZATION_DEFAULT_MODULE);
 
@@ -145,9 +141,6 @@ public class CassandraJamesServerMain implements JamesServerMain {
         new CassandraConsistencyTaskSerializationModule(),
         new CassandraMailboxModule(),
         new CassandraDeletedMessageVaultModule(),
-        new ElasticSearchClientModule(),
-        new ElasticSearchMailboxModule(),
-        new ElasticSearchMetricReporterModule(),
         new MailboxModule(),
         new TikaMailboxModule(),
         new SpamAssassinListenerModule());
@@ -167,7 +160,7 @@ public class CassandraJamesServerMain implements JamesServerMain {
     );
 
     public static void main(String[] args) throws Exception {
-        Configuration configuration = Configuration.builder()
+        CassandraJamesServerConfiguration configuration = CassandraJamesServerConfiguration.builder()
             .useWorkingDirectoryEnvProperty()
             .build();
 
@@ -178,8 +171,9 @@ public class CassandraJamesServerMain implements JamesServerMain {
         JamesServerMain.main(server);
     }
 
-    public static GuiceJamesServer createServer(Configuration configuration) {
+    public static GuiceJamesServer createServer(CassandraJamesServerConfiguration configuration) {
         return GuiceJamesServer.forConfiguration(configuration)
-            .combineWith(ALL_BUT_JMX_CASSANDRA_MODULE);
+            .combineWith(ALL_BUT_JMX_CASSANDRA_MODULE)
+            .combineWith(SearchModuleChooser.chooseModules(configuration.searchConfiguration()));
     }
 }
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchConfiguration.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchConfiguration.java
new file mode 100644
index 0000000..9bc4f5c
--- /dev/null
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchConfiguration.java
@@ -0,0 +1,76 @@
+/****************************************************************
+ * 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;
+
+import static org.apache.james.modules.mailbox.ElasticSearchMailboxModule.ELASTICSEARCH_CONFIGURATION_NAME;
+
+import java.io.FileNotFoundException;
+
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.ex.ConfigurationException;
+import org.apache.james.utils.PropertiesProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SearchConfiguration {
+
+    public enum Implementation {
+        Scanning,
+        ElasticSearch
+    }
+
+    public static SearchConfiguration parse(PropertiesProvider propertiesProvider) throws ConfigurationException {
+        try {
+            Configuration configuration = propertiesProvider.getConfiguration(ELASTICSEARCH_CONFIGURATION_NAME);
+            return SearchConfiguration.from(configuration);
+        } catch (FileNotFoundException e) {
+            LOGGER.warn("Could not find {} configuration file, enabling elasticsearch by default", ELASTICSEARCH_CONFIGURATION_NAME);
+            return elasticSearch();
+        }
+    }
+
+    static SearchConfiguration from(Configuration configuration) {
+        if (configuration.getBoolean("enabled", true)) {
+            return elasticSearch();
+        }
+        return scanning();
+    }
+
+    public static SearchConfiguration scanning() {
+        return new SearchConfiguration(Implementation.Scanning);
+    }
+
+    public static SearchConfiguration elasticSearch() {
+        return new SearchConfiguration(Implementation.ElasticSearch);
+    }
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(SearchConfiguration.class);
+
+
+    private final Implementation implementation;
+
+    public SearchConfiguration(Implementation implementation) {
+        this.implementation = implementation;
+    }
+
+    public Implementation getImplementation() {
+        return implementation;
+    }
+}
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchModuleChooser.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchModuleChooser.java
new file mode 100644
index 0000000..b6713f3
--- /dev/null
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/SearchModuleChooser.java
@@ -0,0 +1,154 @@
+/****************************************************************
+ * 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;
+
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.stream.Stream;
+
+import javax.mail.Flags;
+
+import org.apache.commons.lang3.NotImplementedException;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageUid;
+import org.apache.james.mailbox.events.Group;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.Mailbox;
+import org.apache.james.mailbox.model.MailboxId;
+import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.model.SearchQuery;
+import org.apache.james.mailbox.model.UpdatedFlags;
+import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex;
+import org.apache.james.mailbox.store.search.MessageSearchIndex;
+import org.apache.james.mailbox.store.search.SimpleMessageSearchIndex;
+import org.apache.james.modules.mailbox.ElasticSearchClientModule;
+import org.apache.james.modules.mailbox.ElasticSearchMailboxModule;
+import org.apache.james.modules.server.ReIndexingModule;
+import org.apache.james.quota.search.QuotaSearcher;
+import org.apache.james.quota.search.scanning.ScanningQuotaSearcher;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.AbstractModule;
+import com.google.inject.Module;
+import com.google.inject.Scopes;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class SearchModuleChooser {
+    private static class ScanningQuotaSearchModule extends AbstractModule {
+        @Override
+        protected void configure() {
+            bind(ScanningQuotaSearcher.class).in(Scopes.SINGLETON);
+            bind(QuotaSearcher.class).to(ScanningQuotaSearcher.class);
+        }
+    }
+
+    // Required for CLI
+    private static class FakeMessageSearchIndex extends ListeningMessageSearchIndex {
+        private static class FakeMessageSearchIndexGroup extends Group {
+
+        }
+
+        private static final FakeMessageSearchIndexGroup GROUP = new FakeMessageSearchIndexGroup();
+
+        public FakeMessageSearchIndex() {
+            super(null, null);
+        }
+
+        @Override
+        public Mono<Void> add(MailboxSession session, Mailbox mailbox, MailboxMessage message) {
+            throw new NotImplementedException("not implemented");
+        }
+
+        @Override
+        public Mono<Void> delete(MailboxSession session, Mailbox mailbox, Collection<MessageUid> expungedUids) {
+            throw new NotImplementedException("not implemented");
+        }
+
+        @Override
+        public Mono<Void> deleteAll(MailboxSession session, MailboxId mailboxId) {
+            throw new NotImplementedException("not implemented");
+        }
+
+        @Override
+        public Mono<Void> update(MailboxSession session, Mailbox mailbox, List<UpdatedFlags> updatedFlagsList) {
+            throw new NotImplementedException("not implemented");
+        }
+
+        @Override
+        public Mono<Flags> retrieveIndexedFlags(Mailbox mailbox, MessageUid uid) {
+            throw new NotImplementedException("not implemented");
+        }
+
+        @Override
+        public Group getDefaultGroup() {
+            return GROUP;
+        }
+
+        @Override
+        public Stream<MessageUid> search(MailboxSession session, Mailbox mailbox, SearchQuery searchQuery) throws MailboxException {
+            throw new NotImplementedException("not implemented");
+        }
+
+        @Override
+        public Flux<MessageId> search(MailboxSession session, Collection<MailboxId> mailboxIds, SearchQuery searchQuery, long limit) {
+            throw new NotImplementedException("not implemented");
+        }
+
+        @Override
+        public EnumSet<MailboxManager.SearchCapabilities> getSupportedCapabilities(EnumSet<MailboxManager.MessageCapabilities> messageCapabilities) {
+            throw new NotImplementedException("not implemented");
+        }
+
+        @Override
+        public ExecutionMode getExecutionMode() {
+            throw new NotImplementedException("not implemented");
+        }
+    }
+
+    private static class ScanningSearchModule extends AbstractModule {
+        @Override
+        protected void configure() {
+            bind(MessageSearchIndex.class).to(SimpleMessageSearchIndex.class);
+            bind(FakeMessageSearchIndex.class).in(Scopes.SINGLETON);
+            bind(ListeningMessageSearchIndex.class).to(FakeMessageSearchIndex.class);
+        }
+    }
+
+    public static List<Module> chooseModules(SearchConfiguration searchConfiguration) {
+        switch (searchConfiguration.getImplementation()) {
+            case ElasticSearch:
+                return ImmutableList.of(
+                    new ElasticSearchClientModule(),
+                    new ElasticSearchMailboxModule(),
+                    new ReIndexingModule());
+            case Scanning:
+                return ImmutableList.of(
+                    new ScanningQuotaSearchModule(),
+                    new ScanningSearchModule());
+            default:
+                throw new RuntimeException("Unsupported search implementation " + searchConfiguration.getImplementation());
+        }
+    }
+}
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java
index 4d8b3a9..9a5fd68 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java
@@ -43,7 +43,12 @@ class AuthenticatedCassandraJamesServerTest {
     @Nested
     class AuthenticationTest implements JamesServerContract {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+        JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+            CassandraJamesServerConfiguration.builder()
+                .workingDirectory(tmpDir)
+                .configurationFromClasspath()
+                .searchConfiguration(SearchConfiguration.elasticSearch())
+                .build())
             .extension(new DockerElasticSearchExtension())
             .extension(cassandraExtension)
             .server(configuration -> CassandraJamesServerMain.createServer(configuration)
@@ -59,7 +64,12 @@ class AuthenticatedCassandraJamesServerTest {
     @Nested
     class SslTest {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+        JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+            CassandraJamesServerConfiguration.builder()
+                .workingDirectory(tmpDir)
+                .configurationFromClasspath()
+                .searchConfiguration(SearchConfiguration.elasticSearch())
+                .build())
             .extension(new DockerElasticSearchExtension())
             .extension(cassandraExtension)
             .disableAutoStart()
@@ -84,7 +94,12 @@ class AuthenticatedCassandraJamesServerTest {
     @Nested
     class AuthenticationFailureTest {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+        JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+            CassandraJamesServerConfiguration.builder()
+                .workingDirectory(tmpDir)
+                .configurationFromClasspath()
+                .searchConfiguration(SearchConfiguration.elasticSearch())
+                .build())
             .extension(new DockerElasticSearchExtension())
             .extension(cassandraExtension)
             .disableAutoStart()
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CacheSessionTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CacheSessionTest.java
index 7e2c394..24dfdf3 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CacheSessionTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CacheSessionTest.java
@@ -72,7 +72,12 @@ class CacheSessionTest {
     }
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJamesServerTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJamesServerTest.java
index 9ad366a..cab7b20 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJamesServerTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJamesServerTest.java
@@ -30,7 +30,12 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraJamesServerTest implements JamesServerContract {
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapJamesServerTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapJamesServerTest.java
index 70befac..69fe6a7 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapJamesServerTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapJamesServerTest.java
@@ -27,7 +27,12 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraJmapJamesServerTest implements JmapJamesServerContract {
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapTestRule.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapTestRule.java
index 87cbe45..6a34304 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapTestRule.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapTestRule.java
@@ -23,7 +23,6 @@ import java.io.IOException;
 
 import org.apache.james.modules.TestDockerESMetricReporterModule;
 import org.apache.james.modules.TestJMAPServerModule;
-import org.apache.james.server.core.configuration.Configuration;
 import org.apache.james.webadmin.WebAdminConfiguration;
 import org.junit.rules.TemporaryFolder;
 import org.junit.rules.TestRule;
@@ -55,9 +54,10 @@ public class CassandraJmapTestRule implements TestRule {
     }
 
     public GuiceJamesServer jmapServer(Module... additionals) throws IOException {
-        Configuration configuration = Configuration.builder()
+        CassandraJamesServerConfiguration configuration = CassandraJamesServerConfiguration.builder()
             .workingDirectory(temporaryFolder.newFolder())
             .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build();
 
         return CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMailRepositoryIntegrationTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMailRepositoryIntegrationTest.java
index 5cacc6f..88f0c7b 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMailRepositoryIntegrationTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMailRepositoryIntegrationTest.java
@@ -47,7 +47,12 @@ class CassandraMailRepositoryIntegrationTest {
     private SMTPMessageSender smtpMessageSender = new SMTPMessageSender("other.com");
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMessageIdManagerInjectionTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMessageIdManagerInjectionTest.java
index eef7607..49378ba 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMessageIdManagerInjectionTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraMessageIdManagerInjectionTest.java
@@ -33,7 +33,12 @@ import com.google.inject.multibindings.Multibinder;
 
 class CassandraMessageIdManagerInjectionTest {
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java
index a44e56c..b9bd416 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java
@@ -42,7 +42,12 @@ class CassandraNodeConfTest {
     private static final int CASSANDRA_PORT = 9042;
 
     private static JamesServerBuilder extensionBuilder() {
-        return new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+        return new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+            CassandraJamesServerConfiguration.builder()
+                .workingDirectory(tmpDir)
+                .configurationFromClasspath()
+                .searchConfiguration(SearchConfiguration.elasticSearch())
+                .build())
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
             .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraWithTikaTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraWithTikaTest.java
index 4d822c6..db503ed 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraWithTikaTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraWithTikaTest.java
@@ -25,7 +25,12 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 class CassandraWithTikaTest implements JamesServerContract {
     @RegisterExtension
     static JamesServerExtension testExtension =
-        new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+        new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+            CassandraJamesServerConfiguration.builder()
+                .workingDirectory(tmpDir)
+                .configurationFromClasspath()
+                .searchConfiguration(SearchConfiguration.elasticSearch())
+                .build())
             .extension(new CassandraExtension())
             .extension(new  TikaExtension())
             .extension(new DockerElasticSearchExtension())
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DefaultCassandraJamesServerTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DefaultCassandraJamesServerTest.java
index bd3a158..7bca678 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DefaultCassandraJamesServerTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DefaultCassandraJamesServerTest.java
@@ -33,7 +33,12 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 
 class DefaultCassandraJamesServerTest {
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/ESReporterTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/ESReporterTest.java
index 0d244df..50a1fd4 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/ESReporterTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/ESReporterTest.java
@@ -61,7 +61,12 @@ class ESReporterTest {
     static final DockerElasticSearchExtension elasticSearchExtension = new DockerElasticSearchExtension();
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(elasticSearchExtension)
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesCapabilitiesServerTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesCapabilitiesServerTest.java
index 23d5767..12fd2a1 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesCapabilitiesServerTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesCapabilitiesServerTest.java
@@ -36,7 +36,12 @@ class JamesCapabilitiesServerTest {
     private static final MailboxManager mailboxManager = mock(MailboxManager.class);
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesServerWithRetryConnectionTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesServerWithRetryConnectionTest.java
index c376ea2..387c2fc 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesServerWithRetryConnectionTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesServerWithRetryConnectionTest.java
@@ -46,7 +46,12 @@ class JamesServerWithRetryConnectionTest {
     private static final CassandraExtension dockerCassandra = new CassandraExtension();
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(dockerElasticSearch)
         .extension(dockerCassandra)
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesWithNonCompatibleElasticSearchServerTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesWithNonCompatibleElasticSearchServerTest.java
index 479053b..e6021a2 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesWithNonCompatibleElasticSearchServerTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/JamesWithNonCompatibleElasticSearchServerTest.java
@@ -37,7 +37,12 @@ class JamesWithNonCompatibleElasticSearchServerTest {
     static DockerElasticSearch dockerES2 = new DockerElasticSearch.NoAuth(Images.ELASTICSEARCH_2);
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension(dockerES2))
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/KeyspaceCreationTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/KeyspaceCreationTest.java
index c7a2c3f..8adcc62 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/KeyspaceCreationTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/KeyspaceCreationTest.java
@@ -33,7 +33,12 @@ class KeyspaceCreationTest {
     @Nested
     class CreateWhenKeyspaceExists {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+        JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
             .server(CassandraJamesServerMain::createServer)
@@ -54,7 +59,12 @@ class KeyspaceCreationTest {
     @Nested
     class CreateWhenDoesNotExistAndHasRights {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+        JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
             .server(CassandraJamesServerMain::createServer)
@@ -81,7 +91,12 @@ class KeyspaceCreationTest {
     @Nested
     class CreateWhenDoesNotExistAndDoNotHaveRights {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+        JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
             .server(CassandraJamesServerMain::createServer)
@@ -108,7 +123,12 @@ class KeyspaceCreationTest {
     @Nested
     class StartWhenKeyspaceDoesNotExist {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+        JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
             .server(CassandraJamesServerMain::createServer)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/WithCassandraBlobStoreTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/WithCassandraBlobStoreTest.java
index 86cdfc2..c86d4d8 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/WithCassandraBlobStoreTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/WithCassandraBlobStoreTest.java
@@ -27,7 +27,12 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 class WithCassandraBlobStoreTest implements JmapJamesServerContract, MailsShouldBeWellReceived, JamesServerContract {
 
     @RegisterExtension
-    static JamesServerExtension jamesServerExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension jamesServerExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .extension(new SpamAssassinModuleExtension())
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/modules/mailbox/CassandraSchemaVersionStartUpCheckTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/modules/mailbox/CassandraSchemaVersionStartUpCheckTest.java
index a4a8a36..d1402e9 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/modules/mailbox/CassandraSchemaVersionStartUpCheckTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/modules/mailbox/CassandraSchemaVersionStartUpCheckTest.java
@@ -31,11 +31,13 @@ import java.nio.charset.Charset;
 import java.util.Optional;
 
 import org.apache.james.CassandraExtension;
+import org.apache.james.CassandraJamesServerConfiguration;
 import org.apache.james.CassandraJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.StartUpChecksPerformer.StartUpChecksException;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
@@ -57,7 +59,12 @@ class CassandraSchemaVersionStartUpCheckTest {
     private static CassandraSchemaVersionDAO versionDAO = mock(CassandraSchemaVersionDAO.class);
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-ldap-guice/src/main/java/org/apache/james/CassandraLdapJamesServerMain.java b/server/container/guice/cassandra-ldap-guice/src/main/java/org/apache/james/CassandraLdapJamesServerMain.java
index ce1c6ac..42a8752 100644
--- a/server/container/guice/cassandra-ldap-guice/src/main/java/org/apache/james/CassandraLdapJamesServerMain.java
+++ b/server/container/guice/cassandra-ldap-guice/src/main/java/org/apache/james/CassandraLdapJamesServerMain.java
@@ -23,7 +23,6 @@ import static org.apache.james.CassandraJamesServerMain.ALL_BUT_JMX_CASSANDRA_MO
 
 import org.apache.james.data.LdapUsersRepositoryModule;
 import org.apache.james.modules.server.JMXServerModule;
-import org.apache.james.server.core.configuration.Configuration;
 
 import com.google.inject.Module;
 import com.google.inject.util.Modules;
@@ -33,7 +32,7 @@ public class CassandraLdapJamesServerMain implements JamesServerMain {
         .with(new LdapUsersRepositoryModule());
 
     public static void main(String[] args) throws Exception {
-        Configuration configuration = Configuration.builder()
+        CassandraJamesServerConfiguration configuration = CassandraJamesServerConfiguration.builder()
             .useWorkingDirectoryEnvProperty()
             .build();
 
@@ -44,8 +43,9 @@ public class CassandraLdapJamesServerMain implements JamesServerMain {
         JamesServerMain.main(server);
     }
 
-    static GuiceJamesServer createServer(Configuration configuration) {
+    static GuiceJamesServer createServer(CassandraJamesServerConfiguration configuration) {
         return GuiceJamesServer.forConfiguration(configuration)
-            .combineWith(MODULES);
+            .combineWith(MODULES)
+            .combineWith(SearchModuleChooser.chooseModules(configuration.searchConfiguration()));
     }
 }
diff --git a/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJamesServerTest.java b/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJamesServerTest.java
index f1fba58..8c20b54 100644
--- a/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJamesServerTest.java
+++ b/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJamesServerTest.java
@@ -53,7 +53,12 @@ class CassandraLdapJamesServerTest implements JamesServerContract {
     SMTPMessageSender messageSender = new SMTPMessageSender(Domain.LOCALHOST.asString());
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .extension(new LdapTestExtension())
diff --git a/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJmapJamesServerTest.java b/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJmapJamesServerTest.java
index 3bbb46a..ccf7097 100644
--- a/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJmapJamesServerTest.java
+++ b/server/container/guice/cassandra-ldap-guice/src/test/java/org/apache/james/CassandraLdapJmapJamesServerTest.java
@@ -25,7 +25,12 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraLdapJmapJamesServerTest implements JmapJamesServerContract {
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .extension(new LdapTestExtension())
diff --git a/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/CassandraRabbitMQJamesConfiguration.java b/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/CassandraRabbitMQJamesConfiguration.java
index 83c2b7e..c252ef2 100644
--- a/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/CassandraRabbitMQJamesConfiguration.java
+++ b/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/CassandraRabbitMQJamesConfiguration.java
@@ -35,11 +35,13 @@ import com.github.fge.lambdas.Throwing;
 
 public class CassandraRabbitMQJamesConfiguration implements Configuration {
     public static class Builder {
+        private Optional<SearchConfiguration> searchConfiguration;
         private Optional<BlobStoreConfiguration> blobStoreConfiguration;
         private Optional<String> rootDirectory;
         private Optional<ConfigurationPath> configurationPath;
 
         private Builder() {
+            searchConfiguration = Optional.empty();
             rootDirectory = Optional.empty();
             configurationPath = Optional.empty();
             blobStoreConfiguration = Optional.empty();
@@ -78,17 +80,29 @@ public class CassandraRabbitMQJamesConfiguration implements Configuration {
             return this;
         }
 
+        public Builder searchConfiguration(SearchConfiguration searchConfiguration) {
+            this.searchConfiguration = Optional.of(searchConfiguration);
+            return this;
+        }
+
+
         public CassandraRabbitMQJamesConfiguration build() {
             ConfigurationPath configurationPath = this.configurationPath.orElse(new ConfigurationPath(FileSystem.FILE_PROTOCOL_AND_CONF));
             JamesServerResourceLoader directories = new JamesServerResourceLoader(rootDirectory
                 .orElseThrow(() -> new MissingArgumentException("Server needs a working.directory env entry")));
 
+            BlobStoreConfiguration blobStoreConfiguration = this.blobStoreConfiguration.orElseGet(Throwing.supplier(
+                () -> BlobStoreConfiguration.parse(
+                    new PropertiesProvider(new FileSystemImpl(directories), configurationPath))));
+
+            SearchConfiguration searchConfiguration = this.searchConfiguration.orElseGet(Throwing.supplier(
+                () -> SearchConfiguration.parse(
+                    new PropertiesProvider(new FileSystemImpl(directories), configurationPath))));
+
             return new CassandraRabbitMQJamesConfiguration(
                 configurationPath,
                 directories,
-                blobStoreConfiguration.orElseGet(Throwing.supplier(
-                    () -> BlobStoreConfiguration.parse(
-                        new PropertiesProvider(new FileSystemImpl(directories), configurationPath)))));
+                blobStoreConfiguration, searchConfiguration);
         }
     }
 
@@ -99,11 +113,13 @@ public class CassandraRabbitMQJamesConfiguration implements Configuration {
     private final ConfigurationPath configurationPath;
     private final JamesDirectoriesProvider directories;
     private final BlobStoreConfiguration blobStoreConfiguration;
+    private final SearchConfiguration searchConfiguration;
 
-    public CassandraRabbitMQJamesConfiguration(ConfigurationPath configurationPath, JamesDirectoriesProvider directories, BlobStoreConfiguration blobStoreConfiguration) {
+    public CassandraRabbitMQJamesConfiguration(ConfigurationPath configurationPath, JamesDirectoriesProvider directories, BlobStoreConfiguration blobStoreConfiguration, SearchConfiguration searchConfiguration) {
         this.configurationPath = configurationPath;
         this.directories = directories;
         this.blobStoreConfiguration = blobStoreConfiguration;
+        this.searchConfiguration = searchConfiguration;
     }
 
     @Override
@@ -119,4 +135,8 @@ public class CassandraRabbitMQJamesConfiguration implements Configuration {
     public BlobStoreConfiguration blobStoreConfiguration() {
         return blobStoreConfiguration;
     }
+
+    public SearchConfiguration searchConfiguration() {
+        return searchConfiguration;
+    }
 }
diff --git a/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/CassandraRabbitMQJamesServerMain.java b/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/CassandraRabbitMQJamesServerMain.java
index 38a1816..2e40639 100644
--- a/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/CassandraRabbitMQJamesServerMain.java
+++ b/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/CassandraRabbitMQJamesServerMain.java
@@ -53,10 +53,12 @@ public class CassandraRabbitMQJamesServerMain implements JamesServerMain {
 
     public static GuiceJamesServer createServer(CassandraRabbitMQJamesConfiguration configuration) {
         BlobStoreConfiguration blobStoreConfiguration = configuration.blobStoreConfiguration();
+        SearchConfiguration searchConfiguration = configuration.searchConfiguration();
 
         return GuiceJamesServer.forConfiguration(configuration)
             .combineWith(MODULES)
             .combineWith(BlobStoreModulesChooser.chooseModules(blobStoreConfiguration))
-            .combineWith(BlobStoreCacheModulesChooser.chooseModules(blobStoreConfiguration));
+            .combineWith(BlobStoreCacheModulesChooser.chooseModules(blobStoreConfiguration))
+            .combineWith(SearchModuleChooser.chooseModules(searchConfiguration));
     }
 }
diff --git a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQAwsS3JmapTestRule.java b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQAwsS3JmapTestRule.java
index ccd7ae5..0fe2807 100644
--- a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQAwsS3JmapTestRule.java
+++ b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQAwsS3JmapTestRule.java
@@ -63,6 +63,7 @@ public class CassandraRabbitMQAwsS3JmapTestRule implements TestRule {
             .workingDirectory(temporaryFolder.newFolder())
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build();
 
         return CassandraRabbitMQJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQJamesServerFixture.java b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQJamesServerFixture.java
index 3d220f0..264faac 100644
--- a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQJamesServerFixture.java
+++ b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQJamesServerFixture.java
@@ -41,6 +41,7 @@ public class CassandraRabbitMQJamesServerFixture {
                 .workingDirectory(tmpDir)
                 .configurationFromClasspath()
                 .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+                .searchConfiguration(SearchConfiguration.elasticSearch())
                 .build())
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
diff --git a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQSwiftJmapTestRule.java b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQSwiftJmapTestRule.java
index cf4d2b4..ae2891a 100644
--- a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQSwiftJmapTestRule.java
+++ b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQSwiftJmapTestRule.java
@@ -62,6 +62,7 @@ public class CassandraRabbitMQSwiftJmapTestRule implements TestRule {
             .workingDirectory(temporaryFolder.newFolder())
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build();
 
         return CassandraRabbitMQJamesServerMain.createServer(configuration)
diff --git a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithCacheExtension.java b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithCacheExtension.java
index 85891e6..0df288c 100644
--- a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithCacheExtension.java
+++ b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithCacheExtension.java
@@ -43,6 +43,7 @@ public class WithCacheExtension implements BeforeAllCallback, AfterAllCallback,
                 .workingDirectory(tmpDir)
                 .configurationFromClasspath()
                 .blobStore(BlobStoreConfiguration.objectStorage().enableCache())
+                .searchConfiguration(SearchConfiguration.elasticSearch())
                 .build())
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
diff --git a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithCassandraBlobStore.java b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithCassandraBlobStore.java
index bcb5118..36f9889 100644
--- a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithCassandraBlobStore.java
+++ b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithCassandraBlobStore.java
@@ -42,6 +42,7 @@ public class WithCassandraBlobStore implements BeforeAllCallback, AfterAllCallba
                 .workingDirectory(tmpDir)
                 .configurationFromClasspath()
                 .blobStore(BlobStoreConfiguration.cassandra())
+                .searchConfiguration(SearchConfiguration.elasticSearch())
                 .build())
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
diff --git a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithCacheExtension.java b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithScanningSearchExtension.java
similarity index 93%
copy from server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithCacheExtension.java
copy to server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithScanningSearchExtension.java
index 85891e6..01088b7 100644
--- a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithCacheExtension.java
+++ b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithScanningSearchExtension.java
@@ -33,18 +33,18 @@ import org.junit.jupiter.api.extension.ParameterContext;
 import org.junit.jupiter.api.extension.ParameterResolutionException;
 import org.junit.jupiter.api.extension.ParameterResolver;
 
-public class WithCacheExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback, ParameterResolver {
+public class WithScanningSearchExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback, ParameterResolver {
 
     private final JamesServerExtension jamesServerExtension;
 
-    WithCacheExtension() {
+    WithScanningSearchExtension() {
         jamesServerExtension = new JamesServerBuilder<CassandraRabbitMQJamesConfiguration>(tmpDir ->
             CassandraRabbitMQJamesConfiguration.builder()
                 .workingDirectory(tmpDir)
                 .configurationFromClasspath()
-                .blobStore(BlobStoreConfiguration.objectStorage().enableCache())
+                .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+                .searchConfiguration(SearchConfiguration.scanning())
                 .build())
-            .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
             .extension(new RabbitMQExtension())
             .extension(new AwsS3BlobStoreExtension())
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraWithTikaTest.java b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithScanningSearchTest.java
similarity index 62%
copy from server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraWithTikaTest.java
copy to server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithScanningSearchTest.java
index 4d822c6..ec30cc9 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraWithTikaTest.java
+++ b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/WithScanningSearchTest.java
@@ -19,18 +19,9 @@
 
 package org.apache.james;
 
-import org.apache.james.modules.TestJMAPServerModule;
-import org.junit.jupiter.api.extension.RegisterExtension;
+import org.apache.james.jmap.draft.JmapJamesServerContract;
+import org.junit.jupiter.api.extension.ExtendWith;
 
-class CassandraWithTikaTest implements JamesServerContract {
-    @RegisterExtension
-    static JamesServerExtension testExtension =
-        new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
-            .extension(new CassandraExtension())
-            .extension(new  TikaExtension())
-            .extension(new DockerElasticSearchExtension())
-            .server(configuration -> CassandraJamesServerMain.createServer(configuration)
-                .overrideWith(new TestJMAPServerModule())
-                .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE))
-            .build();
-}
+@ExtendWith(WithScanningSearchExtension.class)
+class WithScanningSearchTest implements JmapJamesServerContract, MailsShouldBeWellReceived, JamesServerContract {
+}
\ No newline at end of file
diff --git a/server/container/guice/cassandra-rabbitmq-ldap-guice/src/main/java/org/apache/james/CassandraRabbitMQLdapJamesServerMain.java b/server/container/guice/cassandra-rabbitmq-ldap-guice/src/main/java/org/apache/james/CassandraRabbitMQLdapJamesServerMain.java
index d91eb1c..0fc0c34 100644
--- a/server/container/guice/cassandra-rabbitmq-ldap-guice/src/main/java/org/apache/james/CassandraRabbitMQLdapJamesServerMain.java
+++ b/server/container/guice/cassandra-rabbitmq-ldap-guice/src/main/java/org/apache/james/CassandraRabbitMQLdapJamesServerMain.java
@@ -29,7 +29,7 @@ import com.google.inject.Module;
 import com.google.inject.util.Modules;
 
 public class CassandraRabbitMQLdapJamesServerMain implements JamesServerMain {
-    public static final Module MODULES = Modules
+    private static final Module MODULES = Modules
         .override(CassandraRabbitMQJamesServerMain.MODULES)
         .with(new LdapUsersRepositoryModule());
 
@@ -47,10 +47,12 @@ public class CassandraRabbitMQLdapJamesServerMain implements JamesServerMain {
 
     public static GuiceJamesServer createServer(CassandraRabbitMQJamesConfiguration configuration) {
         BlobStoreConfiguration blobStoreConfiguration = configuration.blobStoreConfiguration();
+        SearchConfiguration searchConfiguration = configuration.searchConfiguration();
 
         return GuiceJamesServer.forConfiguration(configuration)
             .combineWith(MODULES)
             .combineWith(BlobStoreModulesChooser.chooseModules(blobStoreConfiguration))
-            .combineWith(BlobStoreCacheModulesChooser.chooseModules(blobStoreConfiguration));
+            .combineWith(BlobStoreCacheModulesChooser.chooseModules(blobStoreConfiguration))
+            .combineWith(SearchModuleChooser.chooseModules(searchConfiguration));
     }
 }
diff --git a/server/container/guice/cassandra-rabbitmq-ldap-guice/src/test/java/org/apache/james/CassandraRabbitMQLdapJmapJamesServerTest.java b/server/container/guice/cassandra-rabbitmq-ldap-guice/src/test/java/org/apache/james/CassandraRabbitMQLdapJmapJamesServerTest.java
index 192adbc..ae150ca 100644
--- a/server/container/guice/cassandra-rabbitmq-ldap-guice/src/test/java/org/apache/james/CassandraRabbitMQLdapJmapJamesServerTest.java
+++ b/server/container/guice/cassandra-rabbitmq-ldap-guice/src/test/java/org/apache/james/CassandraRabbitMQLdapJmapJamesServerTest.java
@@ -85,6 +85,7 @@ class CassandraRabbitMQLdapJmapJamesServerTest {
                 .workingDirectory(tmpDir)
                 .configurationFromClasspath()
                 .blobStore(blobStoreConfiguration)
+                .searchConfiguration(SearchConfiguration.elasticSearch())
                 .build())
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
diff --git a/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraImapErrorTest.java b/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraImapErrorTest.java
index fe81740..e4261ab 100644
--- a/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraImapErrorTest.java
+++ b/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraImapErrorTest.java
@@ -26,11 +26,13 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 import org.apache.commons.net.imap.IMAPClient;
 import org.apache.james.CassandraExtension;
+import org.apache.james.CassandraJamesServerConfiguration;
 import org.apache.james.CassandraJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.jmap.draft.JmapGuiceProbe;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.apache.james.modules.protocols.ImapGuiceProbe;
@@ -47,7 +49,12 @@ class CassandraImapErrorTest {
     private final CassandraExtension cassandraExtension = new CassandraExtension();
 
     @RegisterExtension
-    JamesServerExtension serverExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    JamesServerExtension serverExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension())
         .extension(cassandraExtension)
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSendMDNMethodTest.java b/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSendMDNMethodTest.java
index 97b78de..1a171d3 100644
--- a/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSendMDNMethodTest.java
+++ b/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSendMDNMethodTest.java
@@ -20,10 +20,12 @@
 package org.apache.james.jmap.cassandra;
 
 import org.apache.james.CassandraExtension;
+import org.apache.james.CassandraJamesServerConfiguration;
 import org.apache.james.CassandraJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.jmap.draft.methods.integration.SendMDNMethodTest;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.model.MessageId;
@@ -33,7 +35,12 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 public class CassandraSendMDNMethodTest extends SendMDNMethodTest {
 
     @RegisterExtension
-    JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .server(configuration -> CassandraJamesServerMain.createServer(configuration)
diff --git a/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSpamAssassinContractTest.java b/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSpamAssassinContractTest.java
index 429f47a..c06f44b 100644
--- a/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSpamAssassinContractTest.java
+++ b/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSpamAssassinContractTest.java
@@ -19,10 +19,12 @@
 package org.apache.james.jmap.cassandra;
 
 import org.apache.james.CassandraExtension;
+import org.apache.james.CassandraJamesServerConfiguration;
 import org.apache.james.CassandraJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.jmap.draft.methods.integration.SpamAssassinContract;
 import org.apache.james.jmap.draft.methods.integration.SpamAssassinModuleExtension;
 import org.apache.james.modules.TestJMAPServerModule;
@@ -33,7 +35,12 @@ class CassandraSpamAssassinContractTest implements SpamAssassinContract {
     private static final SpamAssassinModuleExtension spamAssassinExtension = new SpamAssassinModuleExtension();
 
     @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraJamesServerConfiguration>(tmpDir ->
+        CassandraJamesServerConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
+            .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .extension(spamAssassinExtension)
diff --git a/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/cucumber/CassandraStepdefs.java b/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/cucumber/CassandraStepdefs.java
index cde2a08..a9fdcab 100644
--- a/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/cucumber/CassandraStepdefs.java
+++ b/server/protocols/jmap-draft-integration-testing/cassandra-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/cassandra/cucumber/CassandraStepdefs.java
@@ -25,10 +25,12 @@ import javax.inject.Inject;
 
 import org.apache.activemq.store.PersistenceAdapter;
 import org.apache.activemq.store.memory.MemoryPersistenceAdapter;
+import org.apache.james.CassandraJamesServerConfiguration;
 import org.apache.james.CassandraJamesServerMain;
 import org.apache.james.CleanupTasksPerformer;
 import org.apache.james.DockerCassandraRule;
 import org.apache.james.DockerElasticSearchRule;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.jmap.draft.methods.integration.cucumber.ImapStepdefs;
 import org.apache.james.jmap.draft.methods.integration.cucumber.MainStepdefs;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
@@ -37,7 +39,6 @@ import org.apache.james.mailbox.store.extractor.DefaultTextExtractor;
 import org.apache.james.modules.TestDockerESMetricReporterModule;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.apache.james.server.CassandraTruncateTableTask;
-import org.apache.james.server.core.configuration.Configuration;
 import org.junit.rules.TemporaryFolder;
 
 import com.github.fge.lambdas.runnable.ThrowingRunnable;
@@ -69,9 +70,10 @@ public class CassandraStepdefs {
         elasticSearch.start();
 
         mainStepdefs.messageIdFactory = new CassandraMessageId.Factory();
-        Configuration configuration = Configuration.builder()
+        CassandraJamesServerConfiguration configuration = CassandraJamesServerConfiguration.builder()
             .workingDirectory(temporaryFolder.newFolder())
             .configurationFromClasspath()
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build();
 
         mainStepdefs.jmapServer = CassandraJamesServerMain.createServer(configuration)
diff --git a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SendMDNMethodTest.java b/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SendMDNMethodTest.java
index 9f526b1..93506b8 100644
--- a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SendMDNMethodTest.java
+++ b/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SendMDNMethodTest.java
@@ -25,6 +25,7 @@ import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.jmap.draft.methods.integration.SendMDNMethodTest;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.model.MessageId;
@@ -42,6 +43,7 @@ public class RabbitMQAwsS3SendMDNMethodTest extends SendMDNMethodTest {
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
diff --git a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SpamAssassinContractTest.java b/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SpamAssassinContractTest.java
index e8f6fbe..b74ddc7 100644
--- a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SpamAssassinContractTest.java
+++ b/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SpamAssassinContractTest.java
@@ -24,6 +24,7 @@ import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.jmap.draft.methods.integration.SpamAssassinContract;
 import org.apache.james.jmap.draft.methods.integration.SpamAssassinModuleExtension;
 import org.apache.james.modules.AwsS3BlobStoreExtension;
@@ -41,6 +42,7 @@ class RabbitMQAwsS3SpamAssassinContractTest implements SpamAssassinContract {
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
diff --git a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/cucumber/awss3/RabbitMQAwsS3Stepdefs.java b/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/cucumber/awss3/RabbitMQAwsS3Stepdefs.java
index 846f808..19bdf2e 100644
--- a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/cucumber/awss3/RabbitMQAwsS3Stepdefs.java
+++ b/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/cucumber/awss3/RabbitMQAwsS3Stepdefs.java
@@ -30,6 +30,7 @@ import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.CleanupTasksPerformer;
 import org.apache.james.DockerCassandraRule;
 import org.apache.james.DockerElasticSearchRule;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.jmap.draft.methods.integration.cucumber.ImapStepdefs;
 import org.apache.james.jmap.draft.methods.integration.cucumber.MainStepdefs;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
@@ -81,6 +82,7 @@ public class RabbitMQAwsS3Stepdefs {
             .workingDirectory(temporaryFolder.newFolder())
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build();
 
         mainStepdefs.jmapServer = CassandraRabbitMQJamesServerMain.createServer(configuration)
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedAuthenticationTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedAuthenticationTest.java
index 8ab8ee8..52f9764 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedAuthenticationTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedAuthenticationTest.java
@@ -25,6 +25,7 @@ import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.jmap.rfc8621.contract.AuthenticationContract;
 import org.apache.james.modules.AwsS3BlobStoreExtension;
 import org.apache.james.modules.RabbitMQExtension;
@@ -39,6 +40,7 @@ class DistributedAuthenticationTest implements AuthenticationContract {
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java
index 1e504db..9827396 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java
@@ -25,6 +25,7 @@ import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.jmap.rfc8621.contract.EchoMethodContract;
 import org.apache.james.modules.AwsS3BlobStoreExtension;
 import org.apache.james.modules.RabbitMQExtension;
@@ -40,6 +41,7 @@ public class DistributedEchoMethodTest implements EchoMethodContract {
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/ConsistencyTasksIntegrationTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/ConsistencyTasksIntegrationTest.java
index 6d9335b..3a5c87a 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/ConsistencyTasksIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/ConsistencyTasksIntegrationTest.java
@@ -46,6 +46,7 @@ import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.backends.cassandra.Scenario.Barrier;
 import org.apache.james.backends.cassandra.TestingSession;
 import org.apache.james.backends.cassandra.init.SessionWithInitializedTablesFactory;
@@ -128,6 +129,7 @@ class ConsistencyTasksIntegrationTest {
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/FixingGhostMailboxTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/FixingGhostMailboxTest.java
index 03bd915..bf73116 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/FixingGhostMailboxTest.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/FixingGhostMailboxTest.java
@@ -49,6 +49,7 @@ import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.backends.cassandra.init.ClusterFactory;
 import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
 import org.apache.james.core.Username;
@@ -115,6 +116,7 @@ class FixingGhostMailboxTest {
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQAuthorizedEndpointsTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQAuthorizedEndpointsTest.java
index e4aeac4..afca267 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQAuthorizedEndpointsTest.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQAuthorizedEndpointsTest.java
@@ -25,6 +25,7 @@ import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.junit.categories.BasicFeature;
 import org.apache.james.modules.AwsS3BlobStoreExtension;
 import org.apache.james.modules.RabbitMQExtension;
@@ -44,6 +45,7 @@ class RabbitMQAuthorizedEndpointsTest extends AuthorizedEndpointsTest {
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQEventDeadLettersIntegrationTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQEventDeadLettersIntegrationTest.java
index 0057187..70ec14c 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQEventDeadLettersIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQEventDeadLettersIntegrationTest.java
@@ -44,6 +44,7 @@ import org.apache.james.GuiceJamesServer;
 import org.apache.james.GuiceModuleTestExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.backends.rabbitmq.DockerRabbitMQ;
 import org.apache.james.core.Username;
 import org.apache.james.junit.categories.BasicFeature;
@@ -205,6 +206,7 @@ class RabbitMQEventDeadLettersIntegrationTest {
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQFastViewProjectionHealthCheckIntegrationTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQFastViewProjectionHealthCheckIntegrationTest.java
index 0871e29..45416a9 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQFastViewProjectionHealthCheckIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQFastViewProjectionHealthCheckIntegrationTest.java
@@ -25,6 +25,7 @@ import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.modules.AwsS3BlobStoreExtension;
 import org.apache.james.modules.RabbitMQExtension;
 import org.apache.james.modules.TestJMAPServerModule;
@@ -40,6 +41,7 @@ class RabbitMQFastViewProjectionHealthCheckIntegrationTest extends FastViewProje
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQForwardIntegrationTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQForwardIntegrationTest.java
index b7b726a..e72de6d 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQForwardIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQForwardIntegrationTest.java
@@ -25,6 +25,7 @@ import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.modules.AwsS3BlobStoreExtension;
 import org.apache.james.modules.RabbitMQExtension;
 import org.apache.james.modules.TestJMAPServerModule;
@@ -40,6 +41,7 @@ class RabbitMQForwardIntegrationTest extends ForwardIntegrationTest {
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQJmapExtension.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQJmapExtension.java
index 8790c35..da86d14 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQJmapExtension.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQJmapExtension.java
@@ -29,6 +29,7 @@ import org.apache.james.CleanupTasksPerformer;
 import org.apache.james.DockerCassandraRule;
 import org.apache.james.DockerElasticSearchRule;
 import org.apache.james.GuiceJamesServer;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.backends.rabbitmq.DockerRabbitMQSingleton;
 import org.apache.james.modules.TestDockerESMetricReporterModule;
 import org.apache.james.modules.TestRabbitMQModule;
@@ -150,6 +151,7 @@ public class RabbitMQJmapExtension implements BeforeAllCallback, AfterAllCallbac
             .workingDirectory(temporaryFolder.newFolder())
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build();
 
         return CassandraRabbitMQJamesServerMain.createServer(configuration)
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQJwtFilterIntegrationTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQJwtFilterIntegrationTest.java
index e3f68d2..fca871b 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQJwtFilterIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQJwtFilterIntegrationTest.java
@@ -25,6 +25,7 @@ import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.jwt.JwtConfiguration;
 import org.apache.james.modules.AwsS3BlobStoreExtension;
 import org.apache.james.modules.RabbitMQExtension;
@@ -42,6 +43,7 @@ class RabbitMQJwtFilterIntegrationTest extends JwtFilterIntegrationTest {
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQReindexingWithEventDeadLettersTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQReindexingWithEventDeadLettersTest.java
index a16607b..fd3168a 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQReindexingWithEventDeadLettersTest.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQReindexingWithEventDeadLettersTest.java
@@ -39,6 +39,7 @@ import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.jmap.AccessToken;
 import org.apache.james.jmap.LocalHostURIBuilder;
 import org.apache.james.jmap.draft.JmapGuiceProbe;
@@ -87,6 +88,7 @@ class RabbitMQReindexingWithEventDeadLettersTest {
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(dockerElasticSearch)
         .extension(new CassandraExtension())
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerIntegrationTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerIntegrationTest.java
index 44cb8dc..7162cb3 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerIntegrationTest.java
@@ -35,6 +35,7 @@ import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
 import org.apache.james.junit.categories.BasicFeature;
 import org.apache.james.modules.AwsS3BlobStoreExtension;
@@ -64,6 +65,7 @@ class RabbitMQWebAdminServerIntegrationTest extends WebAdminServerIntegrationTes
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerTaskSerializationIntegrationTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerTaskSerializationIntegrationTest.java
index 753f992..f0775df 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerTaskSerializationIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerTaskSerializationIntegrationTest.java
@@ -44,6 +44,7 @@ import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
 import org.apache.james.backends.cassandra.versions.SchemaVersion;
 import org.apache.james.core.Username;
@@ -103,6 +104,7 @@ class RabbitMQWebAdminServerTaskSerializationIntegrationTest {
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/vault/RabbitMQDeletedMessageVaultIntegrationTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/vault/RabbitMQDeletedMessageVaultIntegrationTest.java
index 31b6392..c620031 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/vault/RabbitMQDeletedMessageVaultIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/vault/RabbitMQDeletedMessageVaultIntegrationTest.java
@@ -25,6 +25,7 @@ import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.modules.AwsS3BlobStoreExtension;
 import org.apache.james.modules.RabbitMQExtension;
 import org.apache.james.modules.TestJMAPServerModule;
@@ -44,6 +45,7 @@ class RabbitMQDeletedMessageVaultIntegrationTest extends DeletedMessageVaultInte
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(ES_EXTENSION)
         .extension(new CassandraExtension())
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/vault/RabbitMQLinshareBlobExportMechanismIntegrationTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/vault/RabbitMQLinshareBlobExportMechanismIntegrationTest.java
index 2a175d6..ed82af5 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/vault/RabbitMQLinshareBlobExportMechanismIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/vault/RabbitMQLinshareBlobExportMechanismIntegrationTest.java
@@ -25,6 +25,7 @@ import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.SearchConfiguration;
 import org.apache.james.backends.rabbitmq.DockerRabbitMQSingleton;
 import org.apache.james.mailbox.extractor.TextExtractor;
 import org.apache.james.mailbox.store.search.PDFTextExtractor;
@@ -46,6 +47,7 @@ class RabbitMQLinshareBlobExportMechanismIntegrationTest extends LinshareBlobExp
             .workingDirectory(tmpDir)
             .configurationFromClasspath()
             .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
+            .searchConfiguration(SearchConfiguration.elasticSearch())
             .build())
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())


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


[james-project] 05/09: JAMES-3305 Key registration should not crash on invalid messages

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 999655314fb9054cb162992b93672928af0ecb16
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Fri Jul 10 11:43:27 2020 +0700

    JAMES-3305 Key registration should not crash on invalid messages
---
 .../james/mailbox/events/RabbitMQEventBusTest.java | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java b/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
index 58d1979..d2eac1f 100644
--- a/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
+++ b/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
@@ -67,6 +67,7 @@ import org.apache.james.event.json.EventSerializer;
 import org.apache.james.mailbox.events.EventBusTestFixture.GroupA;
 import org.apache.james.mailbox.events.EventBusTestFixture.MailboxListenerCountingSuccessfulExecution;
 import org.apache.james.mailbox.events.EventDispatcher.DispatchingFailureGroup;
+import org.apache.james.mailbox.events.RoutingKeyConverter.RoutingKey;
 import org.apache.james.mailbox.model.TestId;
 import org.apache.james.mailbox.model.TestMessageId;
 import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
@@ -241,6 +242,39 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
     }
 
     @Test
+    void registrationShouldNotCrashOnInvalidMessage() {
+        EventCollector listener = new EventCollector();
+        Mono.from(eventBus.register(listener, KEY_1)).block();
+
+        rabbitMQExtension.getSender()
+            .send(Mono.just(new OutboundMessage(MAILBOX_EVENT_EXCHANGE_NAME,
+                RoutingKey.of(KEY_1).asString(),
+                "BAD_PAYLOAD!".getBytes(StandardCharsets.UTF_8))))
+            .block();
+
+        eventBus.dispatch(EVENT, KEY_1).block();
+        await().timeout(org.awaitility.Duration.TEN_SECONDS)
+            .untilAsserted(() -> assertThat(listener.getEvents()).containsOnly(EVENT));
+    }
+
+    @Test
+    void registrationShouldNotCrashOnInvalidMessages() {
+        EventCollector listener = new EventCollector();
+        Mono.from(eventBus.register(listener, KEY_1)).block();
+
+        IntStream.range(0, 100)
+            .forEach(i -> rabbitMQExtension.getSender()
+                .send(Mono.just(new OutboundMessage(MAILBOX_EVENT_EXCHANGE_NAME,
+                    RoutingKey.of(KEY_1).asString(),
+                    "BAD_PAYLOAD!".getBytes(StandardCharsets.UTF_8))))
+                .block());
+
+        eventBus.dispatch(EVENT, KEY_1).block();
+        await().timeout(org.awaitility.Duration.TEN_SECONDS)
+            .untilAsserted(() -> assertThat(listener.getEvents()).containsOnly(EVENT));
+    }
+
+    @Test
     void deserializeEventCollectorGroup() throws Exception {
         assertThat(Group.deserialize("org.apache.james.mailbox.util.EventCollector$EventCollectorGroup"))
             .isEqualTo(new EventCollector.EventCollectorGroup());


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


[james-project] 04/09: JAMES-3305 Invalid EventBus messages needs to be stored in dead letter queue

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 1de4fa58380d288852b11d02fd6a6291ec38a665
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Fri Jul 10 11:25:01 2020 +0700

    JAMES-3305 Invalid EventBus messages needs to be stored in dead letter queue
---
 .../james/mailbox/events/EventDispatcher.java      | 28 +++++++++++++++++--
 .../james/mailbox/events/GroupRegistration.java    |  5 ++--
 .../james/mailbox/events/RabbitMQEventBus.java     |  2 ++
 .../james/mailbox/events/RabbitMQEventBusTest.java | 32 +++++++++++++++++++++-
 4 files changed, 61 insertions(+), 6 deletions(-)

diff --git a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/EventDispatcher.java b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/EventDispatcher.java
index c150184..999dc40 100644
--- a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/EventDispatcher.java
+++ b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/EventDispatcher.java
@@ -20,9 +20,15 @@
 package org.apache.james.mailbox.events;
 
 import static com.rabbitmq.client.MessageProperties.PERSISTENT_TEXT_PLAIN;
+import static org.apache.james.backends.rabbitmq.Constants.AUTO_DELETE;
 import static org.apache.james.backends.rabbitmq.Constants.DIRECT_EXCHANGE;
 import static org.apache.james.backends.rabbitmq.Constants.DURABLE;
+import static org.apache.james.backends.rabbitmq.Constants.EMPTY_ROUTING_KEY;
+import static org.apache.james.backends.rabbitmq.Constants.EXCLUSIVE;
+import static org.apache.james.backends.rabbitmq.Constants.NO_ARGUMENTS;
 import static org.apache.james.mailbox.events.RabbitMQEventBus.EVENT_BUS_ID;
+import static org.apache.james.mailbox.events.RabbitMQEventBus.MAILBOX_EVENT_DEAD_LETTER_EXCHANGE_NAME;
+import static org.apache.james.mailbox.events.RabbitMQEventBus.MAILBOX_EVENT_DEAD_LETTER_QUEUE;
 import static org.apache.james.mailbox.events.RabbitMQEventBus.MAILBOX_EVENT_EXCHANGE_NAME;
 
 import java.nio.charset.StandardCharsets;
@@ -46,8 +52,10 @@ import com.rabbitmq.client.AMQP;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 import reactor.core.publisher.MonoProcessor;
+import reactor.rabbitmq.BindingSpecification;
 import reactor.rabbitmq.ExchangeSpecification;
 import reactor.rabbitmq.OutboundMessage;
+import reactor.rabbitmq.QueueSpecification;
 import reactor.rabbitmq.Sender;
 import reactor.util.function.Tuples;
 
@@ -83,9 +91,23 @@ public class EventDispatcher {
     }
 
     void start() {
-        sender.declareExchange(ExchangeSpecification.exchange(MAILBOX_EVENT_EXCHANGE_NAME)
-            .durable(DURABLE)
-            .type(DIRECT_EXCHANGE))
+        Flux.concat(
+            sender.declareExchange(ExchangeSpecification.exchange(MAILBOX_EVENT_EXCHANGE_NAME)
+                .durable(DURABLE)
+                .type(DIRECT_EXCHANGE)),
+            sender.declareExchange(ExchangeSpecification.exchange(MAILBOX_EVENT_DEAD_LETTER_EXCHANGE_NAME)
+                .durable(DURABLE)
+                .type(DIRECT_EXCHANGE)),
+            sender.declareQueue(QueueSpecification.queue(MAILBOX_EVENT_DEAD_LETTER_QUEUE)
+                .durable(DURABLE)
+                .exclusive(!EXCLUSIVE)
+                .autoDelete(!AUTO_DELETE)
+                .arguments(NO_ARGUMENTS)),
+            sender.bind(BindingSpecification.binding()
+                .exchange(MAILBOX_EVENT_DEAD_LETTER_EXCHANGE_NAME)
+                .queue(MAILBOX_EVENT_DEAD_LETTER_QUEUE)
+                .routingKey(EMPTY_ROUTING_KEY)))
+            .then()
             .block();
     }
 
diff --git a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/GroupRegistration.java b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/GroupRegistration.java
index d95e6bd..5141ae5 100644
--- a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/GroupRegistration.java
+++ b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/GroupRegistration.java
@@ -23,9 +23,10 @@ import static org.apache.james.backends.rabbitmq.Constants.AUTO_DELETE;
 import static org.apache.james.backends.rabbitmq.Constants.DURABLE;
 import static org.apache.james.backends.rabbitmq.Constants.EMPTY_ROUTING_KEY;
 import static org.apache.james.backends.rabbitmq.Constants.EXCLUSIVE;
-import static org.apache.james.backends.rabbitmq.Constants.NO_ARGUMENTS;
 import static org.apache.james.backends.rabbitmq.Constants.REQUEUE;
+import static org.apache.james.backends.rabbitmq.Constants.deadLetterQueue;
 import static org.apache.james.mailbox.events.RabbitMQEventBus.MAILBOX_EVENT;
+import static org.apache.james.mailbox.events.RabbitMQEventBus.MAILBOX_EVENT_DEAD_LETTER_EXCHANGE_NAME;
 import static org.apache.james.mailbox.events.RabbitMQEventBus.MAILBOX_EVENT_EXCHANGE_NAME;
 
 import java.nio.charset.StandardCharsets;
@@ -124,7 +125,7 @@ class GroupRegistration implements Registration {
                 .durable(DURABLE)
                 .exclusive(!EXCLUSIVE)
                 .autoDelete(!AUTO_DELETE)
-                .arguments(NO_ARGUMENTS)),
+                .arguments(deadLetterQueue(MAILBOX_EVENT_DEAD_LETTER_EXCHANGE_NAME))),
             sender.bind(BindingSpecification.binding()
                 .exchange(MAILBOX_EVENT_EXCHANGE_NAME)
                 .queue(queueName.asString())
diff --git a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RabbitMQEventBus.java b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RabbitMQEventBus.java
index a73f1ed..29dcc6f 100644
--- a/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RabbitMQEventBus.java
+++ b/mailbox/event/event-rabbitmq/src/main/java/org/apache/james/mailbox/events/RabbitMQEventBus.java
@@ -40,7 +40,9 @@ public class RabbitMQEventBus implements EventBus, Startable {
     private static final Set<RegistrationKey> NO_KEY = ImmutableSet.of();
     private static final String NOT_RUNNING_ERROR_MESSAGE = "Event Bus is not running";
     static final String MAILBOX_EVENT = "mailboxEvent";
+    static final String MAILBOX_EVENT_DEAD_LETTER_QUEUE = MAILBOX_EVENT + "-dead-letter-queue";
     static final String MAILBOX_EVENT_EXCHANGE_NAME = MAILBOX_EVENT + "-exchange";
+    static final String MAILBOX_EVENT_DEAD_LETTER_EXCHANGE_NAME = MAILBOX_EVENT + "-dead-letter-exchange";
     static final String EVENT_BUS_ID = "eventBusId";
 
     private final EventSerializer eventSerializer;
diff --git a/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java b/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
index 810187c..58d1979 100644
--- a/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
+++ b/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
@@ -37,6 +37,7 @@ import static org.apache.james.mailbox.events.EventBusTestFixture.newAsyncListen
 import static org.apache.james.mailbox.events.EventBusTestFixture.newListener;
 import static org.apache.james.mailbox.events.GroupRegistration.WorkQueueName.MAILBOX_EVENT_WORK_QUEUE_PREFIX;
 import static org.apache.james.mailbox.events.RabbitMQEventBus.MAILBOX_EVENT;
+import static org.apache.james.mailbox.events.RabbitMQEventBus.MAILBOX_EVENT_DEAD_LETTER_QUEUE;
 import static org.apache.james.mailbox.events.RabbitMQEventBus.MAILBOX_EVENT_EXCHANGE_NAME;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatCode;
@@ -53,6 +54,7 @@ import java.io.Closeable;
 import java.nio.charset.StandardCharsets;
 import java.time.Duration;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
 
@@ -72,6 +74,7 @@ import org.apache.james.mailbox.util.EventCollector;
 import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
 import org.assertj.core.data.Percentage;
+import org.awaitility.Awaitility;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Disabled;
@@ -83,6 +86,7 @@ import org.mockito.stubbing.Answer;
 import com.google.common.collect.ImmutableSet;
 
 import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Schedulers;
 import reactor.rabbitmq.BindingSpecification;
 import reactor.rabbitmq.ExchangeSpecification;
 import reactor.rabbitmq.OutboundMessage;
@@ -212,6 +216,31 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
     }
 
     @Test
+    void eventProcessingShouldStoreInvalidMessagesInDeadLetterQueue() {
+        EventCollector listener = new EventCollector();
+        EventBusTestFixture.GroupA registeredGroup = new EventBusTestFixture.GroupA();
+        eventBus.register(listener, registeredGroup);
+
+        String emptyRoutingKey = "";
+        rabbitMQExtension.getSender()
+            .send(Mono.just(new OutboundMessage(MAILBOX_EVENT_EXCHANGE_NAME,
+                emptyRoutingKey,
+                "BAD_PAYLOAD!".getBytes(StandardCharsets.UTF_8))))
+            .block();
+
+        AtomicInteger deadLetteredCount = new AtomicInteger();
+        rabbitMQExtension.getRabbitChannelPool()
+            .createReceiver()
+            .consumeAutoAck(MAILBOX_EVENT_DEAD_LETTER_QUEUE)
+            .doOnNext(next -> deadLetteredCount.incrementAndGet())
+            .subscribeOn(Schedulers.elastic())
+            .subscribe();
+
+        Awaitility.await().atMost(org.awaitility.Duration.TEN_SECONDS)
+            .untilAsserted(() -> assertThat(deadLetteredCount.get()).isEqualTo(1));
+    }
+
+    @Test
     void deserializeEventCollectorGroup() throws Exception {
         assertThat(Group.deserialize("org.apache.james.mailbox.util.EventCollector$EventCollectorGroup"))
             .isEqualTo(new EventCollector.EventCollectorGroup());
@@ -727,7 +756,8 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
                 eventBusWithKeyHandlerNotStarted.stop();
 
                 assertThat(rabbitManagementAPI.listQueues())
-                    .filteredOn(queue -> !queue.getName().startsWith(MAILBOX_EVENT_WORK_QUEUE_PREFIX))
+                    .filteredOn(queue -> !queue.getName().startsWith(MAILBOX_EVENT_WORK_QUEUE_PREFIX)
+                        && !queue.getName().startsWith(MAILBOX_EVENT_DEAD_LETTER_QUEUE))
                     .isEmpty();
             }
 


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