You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2019/12/18 11:29:47 UTC

[james-project] branch master updated (9638ef4 -> 00fbef8)

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

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


    from 9638ef4  JAMES-2919 MessageFastView projection changelog entry
     new 7d72e5b  JAMES-2555 Single mailbox reIndexing do not need a user parameter
     new be34263  JAMES-2993 ReIndexing routes sould be resource oriented
     new 44175bf  JAMES-2993 Not stopping MemoryTaskManager results in deadlock
     new 3184372  JAMES-2993 Not all guice products supports indexation
     new d436db3  JAMES-2993 Do not expose endpoints when no associated tasks
     new 00fbef8  JAMES-2993 Upgrade instructions for users mailboxes reindexing relocation

The 6 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:
 .../org/apache/james/CassandraJamesServerMain.java |   8 +-
 .../java/org/apache/james/JPAJamesServerMain.java  |   6 +-
 .../james/modules/server/MailboxRoutesModule.java  |   6 +
 .../modules/server/MailboxesRoutesModule.java}     |   6 +-
 .../modules/server/MessageIdReIndexingModule.java  |  34 --
 ...dexingModule.java => MessagesRoutesModule.java} |   6 +-
 .../james/modules/server/ReIndexingModule.java     |  12 +-
 ...dminServerTaskSerializationIntegrationTest.java |   3 +-
 .../webadmin/tasks/TaskFromRequestRegistry.java    |  32 +-
 ...{ReindexingRoutes.java => MailboxesRoutes.java} |  52 +--
 ...IdReindexingRoutes.java => MessagesRoutes.java} |   8 +-
 .../james/webadmin/routes/UserMailboxesRoutes.java |  67 +++-
 ...ingRoutesTest.java => MailboxesRoutesTest.java} | 360 +----------------
 .../webadmin/routes/MalformedUrlRoutesTest.java    |  10 +-
 .../james/webadmin/routes/MessageRoutesTest.java   | 229 +++++++++++
 ...va => UserMailboxesRoutesNoIndexationTest.java} |  90 ++---
 .../webadmin/routes/UserMailboxesRoutesTest.java   | 247 +++++++++++-
 src/site/markdown/server/manage-webadmin.md        | 431 +++++++++++----------
 upgrade-instructions.md                            |  17 +
 19 files changed, 876 insertions(+), 748 deletions(-)
 copy server/container/guice/protocols/{webadmin-mailqueue/src/main/java/org/apache/james/modules/server/MailQueueRoutesModule.java => webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxesRoutesModule.java} (89%)
 delete mode 100644 server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessageIdReIndexingModule.java
 copy server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/{ReIndexingModule.java => MessagesRoutesModule.java} (89%)
 rename server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/{ReindexingRoutes.java => MailboxesRoutes.java} (84%)
 rename server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/{MessageIdReindexingRoutes.java => MessagesRoutes.java} (92%)
 rename server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/{ReindexingRoutesTest.java => MailboxesRoutesTest.java} (71%)
 create mode 100644 server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesTest.java
 copy server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/{MalformedUrlRoutesTest.java => UserMailboxesRoutesNoIndexationTest.java} (53%)


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


[james-project] 01/06: JAMES-2555 Single mailbox reIndexing do not need a user parameter

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

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

commit 7d72e5b7dc2f5e7f709aebda20a9c86b463f26d2
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Dec 16 11:59:59 2019 +0700

    JAMES-2555 Single mailbox reIndexing do not need a user parameter
---
 .../java/org/apache/james/webadmin/routes/ReindexingRoutes.java   | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReindexingRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReindexingRoutes.java
index 12dfcd6..f4223cb 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReindexingRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReindexingRoutes.java
@@ -214,14 +214,6 @@ public class ReindexingRoutes implements Routes {
             value = "Compulsory. Only supported value is `reIndex`"),
         @ApiImplicitParam(
             required = true,
-            name = "user",
-            paramType = "path parameter",
-            dataType = "String",
-            defaultValue = "none",
-            example = "benoit@apache.org",
-            value = "Compulsory. Needs to be a valid username"),
-        @ApiImplicitParam(
-            required = true,
             name = "mailboxId",
             paramType = "path parameter",
             dataType = "String",


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


[james-project] 06/06: JAMES-2993 Upgrade instructions for users mailboxes reindexing relocation

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

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

commit 00fbef8ccbdc1163be1af1f56e5d5e9fe332da9e
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Dec 16 13:31:31 2019 +0700

    JAMES-2993 Upgrade instructions for users mailboxes reindexing relocation
---
 upgrade-instructions.md | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/upgrade-instructions.md b/upgrade-instructions.md
index 1aecc06..f647ae3 100644
--- a/upgrade-instructions.md
+++ b/upgrade-instructions.md
@@ -23,7 +23,24 @@ Change list:
  - [ElasticSearch performance enhancements](#elasticsearch-performance-enhancements)
  - [JAMES-2703 Post 3.4.0 release removals](#james-2703-post-340-release-removals)
  - [Health checks routes return code changes](#health-checks-routes-return-code-changes)
+ - [User mailboxes reIndexing endpoint change](#user-mailboxes-reindexing-endpoint-change)
  
+### User mailboxes reIndexing endpoint change
+ 
+Date 16/12/2019
+
+SHA-1 d68a64d96ba8312ecbd34761e82c9c2c32348290
+
+Concerned products: Guice products
+
+In an effort to have a resource oriented webadmin REST API we decided to relocate the endpoint for user mailbox reIndexing.
+
+`curl -XPOST /mailboxes?task=reIndex&user=bob@apache.org`
+
+Had been moved to:
+
+`curl -XPOST /users/bob@apache.org/mailboxes?task=reIndex`
+
 #### Health checks routes return code changes
 
 Date 10/12/2019


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


[james-project] 05/06: JAMES-2993 Do not expose endpoints when no associated tasks

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

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

commit d436db32bf159c338ad7a8c614166616090bf1a3
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Dec 18 09:22:19 2019 +0700

    JAMES-2993 Do not expose endpoints when no associated tasks
---
 .../webadmin/tasks/TaskFromRequestRegistry.java    | 23 ++++--
 .../james/webadmin/routes/UserMailboxesRoutes.java |  8 +-
 .../UserMailboxesRoutesNoIndexationTest.java       | 92 ++++++++++++++++++++++
 3 files changed, 114 insertions(+), 9 deletions(-)

diff --git a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/tasks/TaskFromRequestRegistry.java b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/tasks/TaskFromRequestRegistry.java
index e823aba..0f01e8a 100644
--- a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/tasks/TaskFromRequestRegistry.java
+++ b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/tasks/TaskFromRequestRegistry.java
@@ -31,7 +31,6 @@ import org.apache.james.task.TaskManager;
 import com.github.fge.lambdas.Throwing;
 import com.github.steveash.guavate.Guavate;
 import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -74,16 +73,28 @@ public class TaskFromRequestRegistry implements TaskFromRequest {
         }
 
         public TaskFromRequestRegistry build() {
-            ImmutableMap<TaskRegistrationKey, TaskFromRequest> registrations = tasks.build();
-            Preconditions.checkState(!registrations.isEmpty());
-            return new TaskFromRequestRegistry(
-                taskParameterName.orElse(DEFAULT_PARAMETER),
-                registrations);
+            return buildAsOptional()
+                .orElseThrow(() -> new IllegalStateException("Expecting some registered tasks but got none"));
         }
 
         public Route buildAsRoute(TaskManager taskManager) {
             return build().asRoute(taskManager);
         }
+
+        public Optional<Route> buildAsRouteOptional(TaskManager taskManager) {
+            return buildAsOptional()
+                .map(registry -> registry.asRoute(taskManager));
+        }
+
+        Optional<TaskFromRequestRegistry> buildAsOptional() {
+            ImmutableMap<TaskRegistrationKey, TaskFromRequest> registrations = tasks.build();
+            if (registrations.isEmpty()) {
+                return Optional.empty();
+            }
+            return Optional.of(new TaskFromRequestRegistry(
+                taskParameterName.orElse(DEFAULT_PARAMETER),
+                registrations));
+        }
     }
 
     public static class TaskRegistration implements TaskFromRequest {
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
index 3281ffc..ddaef99 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
@@ -22,6 +22,7 @@ package org.apache.james.webadmin.routes;
 import static org.apache.james.webadmin.routes.MailboxesRoutes.RE_INDEX;
 import static org.apache.james.webadmin.routes.MailboxesRoutes.TASK_PARAMETER;
 
+import java.util.Optional;
 import java.util.Set;
 
 import javax.inject.Inject;
@@ -124,7 +125,8 @@ public class UserMailboxesRoutes implements Routes {
 
         defineDeleteUserMailboxes();
 
-        service.post(USER_MAILBOXES_BASE, defineReIndexMailboxes(), jsonTransformer);
+        reIndexMailboxesRoute()
+            .ifPresent(route -> service.post(USER_MAILBOXES_BASE, route, jsonTransformer));
     }
 
     @GET
@@ -173,11 +175,11 @@ public class UserMailboxesRoutes implements Routes {
         @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side."),
         @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Bad request - details in the returned error message")
     })
-    public Route defineReIndexMailboxes() {
+    public Optional<Route> reIndexMailboxesRoute() {
         return TaskFromRequestRegistry.builder()
             .parameterName(TASK_PARAMETER)
             .registrations(usersMailboxesTaskRegistration)
-            .buildAsRoute(taskManager);
+            .buildAsRouteOptional(taskManager);
     }
 
     @DELETE
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesNoIndexationTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesNoIndexationTest.java
new file mode 100644
index 0000000..bd8b402
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesNoIndexationTest.java
@@ -0,0 +1,92 @@
+/****************************************************************
+ * 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.webadmin.routes;
+
+import static io.restassured.RestAssured.when;
+import static org.apache.james.webadmin.Constants.SEPARATOR;
+import static org.apache.james.webadmin.routes.UserMailboxesRoutes.USERS_BASE;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.james.core.Username;
+import org.apache.james.mailbox.inmemory.InMemoryMailboxManager;
+import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
+import org.apache.james.task.Hostname;
+import org.apache.james.task.MemoryTaskManager;
+import org.apache.james.user.api.UsersRepository;
+import org.apache.james.webadmin.WebAdminServer;
+import org.apache.james.webadmin.WebAdminUtils;
+import org.apache.james.webadmin.service.UserMailboxesService;
+import org.apache.james.webadmin.utils.ErrorResponder;
+import org.apache.james.webadmin.utils.JsonTransformer;
+import org.eclipse.jetty.http.HttpStatus;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+import io.restassured.RestAssured;
+
+class UserMailboxesRoutesNoIndexationTest {
+    private static final Username USERNAME = Username.of("username");
+
+    private WebAdminServer webAdminServer;
+    private MemoryTaskManager taskManager;
+
+
+    @BeforeEach
+    void setUp() throws Exception {
+        InMemoryMailboxManager mailboxManager = InMemoryIntegrationResources.defaultResources().getMailboxManager();
+        UsersRepository usersRepository = mock(UsersRepository.class);
+        when(usersRepository.contains(USERNAME)).thenReturn(true);
+
+        taskManager = new MemoryTaskManager(new Hostname("foo"));
+
+        webAdminServer = WebAdminUtils.createWebAdminServer(
+            new UserMailboxesRoutes(new UserMailboxesService(mailboxManager, usersRepository), new JsonTransformer(),
+                taskManager,
+                ImmutableSet.of()),
+            new TasksRoutes(taskManager, new JsonTransformer()))
+            .start();
+
+        RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminServer)
+            .setBasePath(USERS_BASE + SEPARATOR + USERNAME.asString() + SEPARATOR + UserMailboxesRoutes.MAILBOXES)
+            .build();
+    }
+
+    @AfterEach
+    void tearDown() {
+        webAdminServer.destroy();
+        taskManager.stop();
+    }
+
+    @Test
+    void postShouldNotBeExposedWhenNoTasks() {
+        when()
+            .post()
+        .then()
+            .statusCode(HttpStatus.NOT_FOUND_404)
+            .body("statusCode", Matchers.is(404))
+            .body("type", Matchers.is(ErrorResponder.ErrorType.NOT_FOUND.getType()))
+            .body("message", Matchers.is("POST /users/username/mailboxes can not be found"));
+    }
+}


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


[james-project] 04/06: JAMES-2993 Not all guice products supports indexation

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

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

commit 3184372c30aa2031b6bcc09350572b095d5eafee
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Tue Dec 17 10:07:39 2019 +0700

    JAMES-2993 Not all guice products supports indexation
    
    This is not the case of memory which relies on scrolling search
---
 .../org/apache/james/CassandraJamesServerMain.java |  2 ++
 .../java/org/apache/james/JPAJamesServerMain.java  |  6 ++--
 .../james/modules/server/MailboxRoutesModule.java  |  6 ++++
 ...lboxRoutesModule.java => ReIndexingModule.java} | 28 ++++++------------
 .../webadmin/tasks/TaskFromRequestRegistry.java    |  9 ++++--
 .../james/webadmin/routes/UserMailboxesRoutes.java | 34 +++++++++++++++-------
 .../webadmin/routes/MalformedUrlRoutesTest.java    |  8 +++--
 .../webadmin/routes/UserMailboxesRoutesTest.java   |  4 ++-
 8 files changed, 59 insertions(+), 38 deletions(-)

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 84953d0..67bf8b5 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
@@ -64,6 +64,7 @@ import org.apache.james.modules.server.MailRepositoriesRoutesModule;
 import org.apache.james.modules.server.MailboxRoutesModule;
 import org.apache.james.modules.server.MailboxesRoutesModule;
 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;
@@ -91,6 +92,7 @@ public class CassandraJamesServerMain {
         new SwaggerRoutesModule(),
         new WebAdminServerModule(),
         new DLPRoutesModule(),
+        new ReIndexingModule(),
         new SieveRoutesModule(),
         new MailboxesRoutesModule(),
         new MessagesRoutesModule());
diff --git a/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java b/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java
index 2fb60b8..b4f2b64 100644
--- a/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java
+++ b/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java
@@ -44,6 +44,7 @@ import org.apache.james.modules.server.MailboxRoutesModule;
 import org.apache.james.modules.server.MailboxesRoutesModule;
 import org.apache.james.modules.server.NoJwtModule;
 import org.apache.james.modules.server.RawPostDequeueDecoratorModule;
+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;
@@ -60,11 +61,12 @@ public class JPAJamesServerMain {
         new WebAdminServerModule(),
         new DataRoutesModules(),
         new MailboxRoutesModule(),
+        new MailboxesRoutesModule(),
         new MailQueueRoutesModule(),
         new MailRepositoriesRoutesModule(),
+        new ReIndexingModule(),
         new SwaggerRoutesModule(),
-        new SieveRoutesModule(),
-        new MailboxesRoutesModule());
+        new SieveRoutesModule());
 
     public static final Module PROTOCOLS = Modules.combine(
         new IMAPServerModule(),
diff --git a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java
index b942500..9b05566 100644
--- a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java
+++ b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.modules.server;
 
+import static org.apache.james.webadmin.routes.UserMailboxesRoutes.USER_MAILBOXES_OPERATIONS_INJECTION_KEY;
+
 import org.apache.james.webadmin.Routes;
 import org.apache.james.webadmin.jackson.QuotaModule;
 import org.apache.james.webadmin.routes.DomainQuotaRoutes;
@@ -26,10 +28,12 @@ import org.apache.james.webadmin.routes.EventDeadLettersRoutes;
 import org.apache.james.webadmin.routes.GlobalQuotaRoutes;
 import org.apache.james.webadmin.routes.UserMailboxesRoutes;
 import org.apache.james.webadmin.routes.UserQuotaRoutes;
+import org.apache.james.webadmin.tasks.TaskFromRequestRegistry.TaskRegistration;
 import org.apache.james.webadmin.utils.JsonTransformerModule;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.multibindings.Multibinder;
+import com.google.inject.name.Names;
 
 public class MailboxRoutesModule extends AbstractModule {
 
@@ -44,5 +48,7 @@ public class MailboxRoutesModule extends AbstractModule {
 
         Multibinder<JsonTransformerModule> jsonTransformerModuleMultibinder = Multibinder.newSetBinder(binder(), JsonTransformerModule.class);
         jsonTransformerModuleMultibinder.addBinding().to(QuotaModule.class);
+
+        Multibinder.newSetBinder(binder(), TaskRegistration.class, Names.named(USER_MAILBOXES_OPERATIONS_INJECTION_KEY));
     }
 }
diff --git a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/ReIndexingModule.java
similarity index 53%
copy from server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java
copy to server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/ReIndexingModule.java
index b942500..8825cf6 100644
--- a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java
+++ b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/ReIndexingModule.java
@@ -19,30 +19,20 @@
 
 package org.apache.james.modules.server;
 
-import org.apache.james.webadmin.Routes;
-import org.apache.james.webadmin.jackson.QuotaModule;
-import org.apache.james.webadmin.routes.DomainQuotaRoutes;
-import org.apache.james.webadmin.routes.EventDeadLettersRoutes;
-import org.apache.james.webadmin.routes.GlobalQuotaRoutes;
-import org.apache.james.webadmin.routes.UserMailboxesRoutes;
-import org.apache.james.webadmin.routes.UserQuotaRoutes;
-import org.apache.james.webadmin.utils.JsonTransformerModule;
+import static org.apache.james.webadmin.routes.UserMailboxesRoutes.USER_MAILBOXES_OPERATIONS_INJECTION_KEY;
+
+import org.apache.james.webadmin.routes.UserMailboxesRoutes.UserReIndexingTaskRegistration;
+import org.apache.james.webadmin.tasks.TaskFromRequestRegistry.TaskRegistration;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.multibindings.Multibinder;
+import com.google.inject.name.Names;
 
-public class MailboxRoutesModule extends AbstractModule {
-
+public class ReIndexingModule extends AbstractModule {
     @Override
     protected void configure() {
-        Multibinder<Routes> routesMultibinder = Multibinder.newSetBinder(binder(), Routes.class);
-        routesMultibinder.addBinding().to(DomainQuotaRoutes.class);
-        routesMultibinder.addBinding().to(EventDeadLettersRoutes.class);
-        routesMultibinder.addBinding().to(GlobalQuotaRoutes.class);
-        routesMultibinder.addBinding().to(UserQuotaRoutes.class);
-        routesMultibinder.addBinding().to(UserMailboxesRoutes.class);
-
-        Multibinder<JsonTransformerModule> jsonTransformerModuleMultibinder = Multibinder.newSetBinder(binder(), JsonTransformerModule.class);
-        jsonTransformerModuleMultibinder.addBinding().to(QuotaModule.class);
+        Multibinder.newSetBinder(binder(), TaskRegistration.class, Names.named(USER_MAILBOXES_OPERATIONS_INJECTION_KEY))
+            .addBinding()
+            .to(UserReIndexingTaskRegistration.class);
     }
 }
diff --git a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/tasks/TaskFromRequestRegistry.java b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/tasks/TaskFromRequestRegistry.java
index 505e4f1..e823aba 100644
--- a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/tasks/TaskFromRequestRegistry.java
+++ b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/tasks/TaskFromRequestRegistry.java
@@ -19,7 +19,7 @@
 
 package org.apache.james.webadmin.tasks;
 
-import java.util.Arrays;
+import java.util.Collection;
 import java.util.Map;
 import java.util.Optional;
 import java.util.function.Function;
@@ -34,6 +34,7 @@ import com.google.common.base.Joiner;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 
 import spark.Request;
 import spark.Route;
@@ -56,7 +57,11 @@ public class TaskFromRequestRegistry implements TaskFromRequest {
         }
 
         public Builder registrations(TaskRegistration... taskRegistrations) {
-            this.tasks.putAll(Arrays.stream(taskRegistrations)
+            return this.registrations(ImmutableSet.copyOf(taskRegistrations));
+        }
+
+        public Builder registrations(Collection<TaskRegistration> taskRegistrations) {
+            this.tasks.putAll(taskRegistrations.stream()
                 .collect(Guavate.toImmutableMap(
                     TaskRegistration::registrationKey,
                     Function.identity())));
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
index 9e040a0..3281ffc 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
@@ -22,7 +22,10 @@ package org.apache.james.webadmin.routes;
 import static org.apache.james.webadmin.routes.MailboxesRoutes.RE_INDEX;
 import static org.apache.james.webadmin.routes.MailboxesRoutes.TASK_PARAMETER;
 
+import java.util.Set;
+
 import javax.inject.Inject;
+import javax.inject.Named;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
@@ -32,12 +35,12 @@ import javax.ws.rs.Produces;
 
 import org.apache.james.core.Username;
 import org.apache.james.mailbox.indexer.ReIndexer;
-import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.task.TaskManager;
 import org.apache.james.webadmin.Constants;
 import org.apache.james.webadmin.Routes;
 import org.apache.james.webadmin.service.UserMailboxesService;
 import org.apache.james.webadmin.tasks.TaskFromRequestRegistry;
+import org.apache.james.webadmin.tasks.TaskFromRequestRegistry.TaskRegistration;
 import org.apache.james.webadmin.tasks.TaskIdDto;
 import org.apache.james.webadmin.utils.ErrorResponder;
 import org.apache.james.webadmin.utils.ErrorResponder.ErrorType;
@@ -65,6 +68,18 @@ import spark.Service;
 public class UserMailboxesRoutes implements Routes {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(UserMailboxesRoutes.class);
+    public static final String USER_MAILBOXES_OPERATIONS_INJECTION_KEY = "userMailboxesOperations";
+
+    public static class UserReIndexingTaskRegistration extends TaskRegistration {
+        @Inject
+        public UserReIndexingTaskRegistration(ReIndexer reIndexer) {
+            super(RE_INDEX, request -> reIndexer.reIndex(getUsernameParam(request)));
+        }
+    }
+
+    private static Username getUsernameParam(Request request) {
+        return Username.of(request.params(USER_NAME));
+    }
 
     public static final String MAILBOX_NAME = ":mailboxName";
     public static final String MAILBOXES = "mailboxes";
@@ -76,17 +91,18 @@ public class UserMailboxesRoutes implements Routes {
     private final UserMailboxesService userMailboxesService;
     private final JsonTransformer jsonTransformer;
     private final TaskManager taskManager;
-    private final MailboxId.Factory mailboxIdFactory;
-    private final ReIndexer reIndexer;
+    private final Set<TaskRegistration> usersMailboxesTaskRegistration;
     private Service service;
 
     @Inject
-    UserMailboxesRoutes(UserMailboxesService userMailboxesService, JsonTransformer jsonTransformer, TaskManager taskManager, MailboxId.Factory mailboxIdFactory, ReIndexer reIndexer) {
+    UserMailboxesRoutes(UserMailboxesService userMailboxesService,
+                        JsonTransformer jsonTransformer,
+                        TaskManager taskManager,
+                        @Named(USER_MAILBOXES_OPERATIONS_INJECTION_KEY) Set<TaskRegistration> usersMailboxesTaskRegistration) {
         this.userMailboxesService = userMailboxesService;
         this.jsonTransformer = jsonTransformer;
         this.taskManager = taskManager;
-        this.mailboxIdFactory = mailboxIdFactory;
-        this.reIndexer = reIndexer;
+        this.usersMailboxesTaskRegistration = usersMailboxesTaskRegistration;
     }
 
     @Override
@@ -160,7 +176,7 @@ public class UserMailboxesRoutes implements Routes {
     public Route defineReIndexMailboxes() {
         return TaskFromRequestRegistry.builder()
             .parameterName(TASK_PARAMETER)
-            .register(RE_INDEX, request -> reIndexer.reIndex(getUsernameParam(request)))
+            .registrations(usersMailboxesTaskRegistration)
             .buildAsRoute(taskManager);
     }
 
@@ -323,8 +339,4 @@ public class UserMailboxesRoutes implements Routes {
             }
         });
     }
-
-    private Username getUsernameParam(Request request) {
-        return Username.of(request.params(USER_NAME));
-    }
 }
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MalformedUrlRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MalformedUrlRoutesTest.java
index 1589fde..a768c3f 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MalformedUrlRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MalformedUrlRoutesTest.java
@@ -35,8 +35,6 @@ import java.nio.charset.StandardCharsets;
 
 import org.apache.james.core.Username;
 import org.apache.james.mailbox.MailboxManager;
-import org.apache.james.mailbox.indexer.ReIndexer;
-import org.apache.james.mailbox.inmemory.InMemoryId;
 import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
 import org.apache.james.task.Hostname;
 import org.apache.james.task.MemoryTaskManager;
@@ -44,15 +42,19 @@ import org.apache.james.user.api.UsersRepository;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.WebAdminUtils;
 import org.apache.james.webadmin.service.UserMailboxesService;
+import org.apache.james.webadmin.tasks.TaskFromRequestRegistry;
 import org.apache.james.webadmin.utils.JsonTransformer;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
+import com.google.common.collect.ImmutableSet;
+
 class MalformedUrlRoutesTest {
     private static final Username USERNAME = Username.of("username");
     private static final String MALFORMED_MAILBOX_NAME = "inbox%work";
+    private static final ImmutableSet<TaskFromRequestRegistry.TaskRegistration> NO_TASKS = ImmutableSet.of();
 
     private WebAdminServer webAdminServer;
     private UsersRepository usersRepository;
@@ -64,7 +66,7 @@ class MalformedUrlRoutesTest {
         MemoryTaskManager taskManager = new MemoryTaskManager(new Hostname("foo"));
         webAdminServer = WebAdminUtils.createWebAdminServer(
             new UserMailboxesRoutes(new UserMailboxesService(mailboxManager, usersRepository), new JsonTransformer(),
-                taskManager, new InMemoryId.Factory(), mock(ReIndexer.class)))
+                taskManager, NO_TASKS))
             .start();
     }
 
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
index c73e71e..2dc0a3b 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
@@ -79,6 +79,7 @@ import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 
 import io.restassured.RestAssured;
 import io.restassured.http.ContentType;
@@ -111,7 +112,8 @@ class UserMailboxesRoutesTest {
 
         webAdminServer = WebAdminUtils.createWebAdminServer(
                 new UserMailboxesRoutes(new UserMailboxesService(mailboxManager, usersRepository), new JsonTransformer(),
-                    taskManager, mailboxIdFactory, reIndexer),
+                    taskManager,
+                    ImmutableSet.of(new UserMailboxesRoutes.UserReIndexingTaskRegistration(reIndexer))),
                 new TasksRoutes(taskManager, new JsonTransformer()))
             .start();
 


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


[james-project] 02/06: JAMES-2993 ReIndexing routes sould be resource oriented

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

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

commit be34263dd35267c9cd858a5c31cd4bc446c5e575
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Dec 16 13:27:38 2019 +0700

    JAMES-2993 ReIndexing routes sould be resource oriented
    
     - Rename ReIndexingRoutes into MailboxesRoutes
     - Rename MessageIdReindexingRoutes into message routes
     - Move user mailbox reIndexing
    
    Was `XPOST /mailboxes?user=bob@apache.org&task=reIndex`
    
    Now `XPOST /users/bob@apache.org/mailboxes?task=reIndex`
---
 .../org/apache/james/CassandraJamesServerMain.java |   8 +-
 .../java/org/apache/james/JPAJamesServerMain.java  |   4 +-
 ...exingModule.java => MailboxesRoutesModule.java} |   6 +-
 ...dexingModule.java => MessagesRoutesModule.java} |   6 +-
 ...dminServerTaskSerializationIntegrationTest.java |   3 +-
 ...{ReindexingRoutes.java => MailboxesRoutes.java} |  44 +--
 ...IdReindexingRoutes.java => MessagesRoutes.java} |   8 +-
 .../james/webadmin/routes/UserMailboxesRoutes.java |  45 ++-
 ...ingRoutesTest.java => MailboxesRoutesTest.java} | 356 +----------------
 .../webadmin/routes/MalformedUrlRoutesTest.java    |   8 +-
 .../james/webadmin/routes/MessageRoutesTest.java   | 235 +++++++++++
 .../webadmin/routes/UserMailboxesRoutesTest.java   | 243 +++++++++++-
 src/site/markdown/server/manage-webadmin.md        | 431 +++++++++++----------
 13 files changed, 759 insertions(+), 638 deletions(-)

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 d6c1a37..84953d0 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
@@ -62,8 +62,8 @@ import org.apache.james.modules.server.JMXServerModule;
 import org.apache.james.modules.server.MailQueueRoutesModule;
 import org.apache.james.modules.server.MailRepositoriesRoutesModule;
 import org.apache.james.modules.server.MailboxRoutesModule;
-import org.apache.james.modules.server.MessageIdReIndexingModule;
-import org.apache.james.modules.server.ReIndexingModule;
+import org.apache.james.modules.server.MailboxesRoutesModule;
+import org.apache.james.modules.server.MessagesRoutesModule;
 import org.apache.james.modules.server.SieveRoutesModule;
 import org.apache.james.modules.server.SwaggerRoutesModule;
 import org.apache.james.modules.server.TaskManagerModule;
@@ -92,8 +92,8 @@ public class CassandraJamesServerMain {
         new WebAdminServerModule(),
         new DLPRoutesModule(),
         new SieveRoutesModule(),
-        new ReIndexingModule(),
-        new MessageIdReIndexingModule());
+        new MailboxesRoutesModule(),
+        new MessagesRoutesModule());
 
     public static final Module PROTOCOLS = Modules.combine(
         new CassandraJmapModule(),
diff --git a/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java b/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java
index 4347b9a..2fb60b8 100644
--- a/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java
+++ b/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java
@@ -41,9 +41,9 @@ import org.apache.james.modules.server.JMXServerModule;
 import org.apache.james.modules.server.MailQueueRoutesModule;
 import org.apache.james.modules.server.MailRepositoriesRoutesModule;
 import org.apache.james.modules.server.MailboxRoutesModule;
+import org.apache.james.modules.server.MailboxesRoutesModule;
 import org.apache.james.modules.server.NoJwtModule;
 import org.apache.james.modules.server.RawPostDequeueDecoratorModule;
-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;
@@ -64,7 +64,7 @@ public class JPAJamesServerMain {
         new MailRepositoriesRoutesModule(),
         new SwaggerRoutesModule(),
         new SieveRoutesModule(),
-        new ReIndexingModule());
+        new MailboxesRoutesModule());
 
     public static final Module PROTOCOLS = Modules.combine(
         new IMAPServerModule(),
diff --git a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessageIdReIndexingModule.java b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxesRoutesModule.java
similarity index 88%
rename from server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessageIdReIndexingModule.java
rename to server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxesRoutesModule.java
index 19f09ba..9075f34 100644
--- a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessageIdReIndexingModule.java
+++ b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxesRoutesModule.java
@@ -20,15 +20,15 @@
 package org.apache.james.modules.server;
 
 import org.apache.james.webadmin.Routes;
-import org.apache.james.webadmin.routes.MessageIdReindexingRoutes;
+import org.apache.james.webadmin.routes.MailboxesRoutes;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.multibindings.Multibinder;
 
-public class MessageIdReIndexingModule extends AbstractModule {
+public class MailboxesRoutesModule extends AbstractModule {
     @Override
     protected void configure() {
         Multibinder<Routes> routesMultibinder = Multibinder.newSetBinder(binder(), Routes.class);
-        routesMultibinder.addBinding().to(MessageIdReindexingRoutes.class);
+        routesMultibinder.addBinding().to(MailboxesRoutes.class);
     }
 }
diff --git a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/ReIndexingModule.java b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessagesRoutesModule.java
similarity index 89%
rename from server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/ReIndexingModule.java
rename to server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessagesRoutesModule.java
index d1902ad..8af3a00 100644
--- a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/ReIndexingModule.java
+++ b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessagesRoutesModule.java
@@ -20,15 +20,15 @@
 package org.apache.james.modules.server;
 
 import org.apache.james.webadmin.Routes;
-import org.apache.james.webadmin.routes.ReindexingRoutes;
+import org.apache.james.webadmin.routes.MessagesRoutes;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.multibindings.Multibinder;
 
-public class ReIndexingModule extends AbstractModule {
+public class MessagesRoutesModule extends AbstractModule {
     @Override
     protected void configure() {
         Multibinder<Routes> routesMultibinder = Multibinder.newSetBinder(binder(), Routes.class);
-        routesMultibinder.addBinding().to(ReindexingRoutes.class);
+        routesMultibinder.addBinding().to(MessagesRoutes.class);
     }
 }
diff --git a/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminServerTaskSerializationIntegrationTest.java b/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminServerTaskSerializationIntegrationTest.java
index 9d633b0..1b1f007 100644
--- a/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminServerTaskSerializationIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminServerTaskSerializationIntegrationTest.java
@@ -311,9 +311,8 @@ public class WebAdminServerTaskSerializationIntegrationTest {
     @Test
     public void userReindexingShouldComplete() {
         String taskId = with()
-                .queryParam("user", USERNAME)
                 .queryParam("task", "reIndex")
-            .post("/mailboxes")
+            .post("users/" + USERNAME + "/mailboxes")
                 .jsonPath()
                 .get("taskId");
 
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReindexingRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MailboxesRoutes.java
similarity index 86%
rename from server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReindexingRoutes.java
rename to server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MailboxesRoutes.java
index f4223cb..5d644fd 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReindexingRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MailboxesRoutes.java
@@ -24,7 +24,6 @@ import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 
-import org.apache.james.core.Username;
 import org.apache.james.mailbox.MessageUid;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MailboxNotFoundException;
@@ -53,7 +52,6 @@ import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
-import spark.HaltException;
 import spark.Request;
 import spark.Route;
 import spark.Service;
@@ -61,11 +59,8 @@ import spark.Service;
 @Api(tags = "ReIndexing (mailboxes)")
 @Path("/mailboxes")
 @Produces("application/json")
-public class ReindexingRoutes implements Routes {
-
-
+public class MailboxesRoutes implements Routes {
     private static final String BASE_PATH = "/mailboxes";
-    private static final String USER_QUERY_PARAM = "user";
     private static final String RE_INDEX_FAILED_MESSAGES_QUERY_PARAM = "reIndexFailedMessagesOf";
     private static final String MAILBOX_PARAM = ":mailbox";
     private static final String UID_PARAM = ":uid";
@@ -81,7 +76,7 @@ public class ReindexingRoutes implements Routes {
     private final JsonTransformer jsonTransformer;
 
     @Inject
-    ReindexingRoutes(TaskManager taskManager, PreviousReIndexingService previousReIndexingService, MailboxId.Factory mailboxIdFactory, ReIndexer reIndexer, JsonTransformer jsonTransformer) {
+    MailboxesRoutes(TaskManager taskManager, PreviousReIndexingService previousReIndexingService, MailboxId.Factory mailboxIdFactory, ReIndexer reIndexer, JsonTransformer jsonTransformer) {
         this.taskManager = taskManager;
         this.previousReIndexingService = previousReIndexingService;
         this.mailboxIdFactory = mailboxIdFactory;
@@ -114,13 +109,6 @@ public class ReindexingRoutes implements Routes {
             example = "?task=reIndex",
             value = "Compulsory. Only supported value is `reIndex`"),
         @ApiImplicitParam(
-            name = "user",
-            paramType = "query parameter",
-            dataType = "String",
-            defaultValue = "none",
-            example = "?user=toto%40domain.tld",
-            value = "optional. If present, only mailboxes of that user will be reIndexed."),
-        @ApiImplicitParam(
             name = "reIndexFailedMessagesOf",
             paramType = "query parameter",
             dataType = "String",
@@ -142,14 +130,7 @@ public class ReindexingRoutes implements Routes {
     }
 
     private Task reIndexAll(Request request) throws MailboxException {
-        boolean userReIndexing = !Strings.isNullOrEmpty(request.queryParams(USER_QUERY_PARAM));
         boolean indexingCorrection = !Strings.isNullOrEmpty(request.queryParams(RE_INDEX_FAILED_MESSAGES_QUERY_PARAM));
-        if (userReIndexing && indexingCorrection) {
-            throw rejectInvalidQueryParameterCombination();
-        }
-        if (userReIndexing) {
-            return reIndexer.reIndex(extractUser(request));
-        }
         if (indexingCorrection) {
             IndexingDetailInformation indexingDetailInformation = retrieveIndexingExecutionDetails(request);
             return reIndexer.reIndex(indexingDetailInformation.failures());
@@ -192,14 +173,6 @@ public class ReindexingRoutes implements Routes {
         }
     }
 
-    private HaltException rejectInvalidQueryParameterCombination() {
-        return ErrorResponder.builder()
-            .statusCode(HttpStatus.BAD_REQUEST_400)
-            .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
-            .message("Can not specify '" + USER_QUERY_PARAM + "' and '" + RE_INDEX_FAILED_MESSAGES_QUERY_PARAM + "' query parameters at the same time")
-            .haltError();
-    }
-
     @POST
     @Path("/{mailboxId}")
     @ApiOperation(value = "Re-indexes all the mails in a mailbox")
@@ -289,19 +262,6 @@ public class ReindexingRoutes implements Routes {
         };
     }
 
-    private Username extractUser(Request request) {
-        try {
-            return Username.of(request.queryParams(USER_QUERY_PARAM));
-        } catch (Exception e) {
-            throw ErrorResponder.builder()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
-                .message("Error while parsing 'user'")
-                .cause(e)
-                .haltError();
-        }
-    }
-
     private MailboxId extractMailboxId(Request request) {
         try {
             return mailboxIdFactory.fromString(request.params(MAILBOX_PARAM));
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MessageIdReindexingRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MessagesRoutes.java
similarity index 92%
rename from server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MessageIdReindexingRoutes.java
rename to server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MessagesRoutes.java
index a283262..45d235f 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MessageIdReindexingRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MessagesRoutes.java
@@ -19,7 +19,7 @@
 
 package org.apache.james.webadmin.routes;
 
-import static org.apache.james.webadmin.routes.ReindexingRoutes.TASK_PARAMETER;
+import static org.apache.james.webadmin.routes.MailboxesRoutes.TASK_PARAMETER;
 
 import javax.inject.Inject;
 import javax.ws.rs.POST;
@@ -49,7 +49,7 @@ import spark.Service;
 @Api(tags = "MessageIdReIndexing")
 @Path("/messages")
 @Produces("application/json")
-public class MessageIdReindexingRoutes implements Routes {
+public class MessagesRoutes implements Routes {
     private static final String MESSAGE_ID_PARAM = ":messageId";
     private static final String BASE_PATH = "/messages";
     private static final String MESSAGE_PATH = BASE_PATH + "/" + MESSAGE_ID_PARAM;
@@ -60,7 +60,7 @@ public class MessageIdReindexingRoutes implements Routes {
     private final JsonTransformer jsonTransformer;
 
     @Inject
-    MessageIdReindexingRoutes(TaskManager taskManager, MessageId.Factory messageIdFactory, MessageIdReIndexer reIndexer, JsonTransformer jsonTransformer) {
+    MessagesRoutes(TaskManager taskManager, MessageId.Factory messageIdFactory, MessageIdReIndexer reIndexer, JsonTransformer jsonTransformer) {
         this.taskManager = taskManager;
         this.messageIdFactory = messageIdFactory;
         this.reIndexer = reIndexer;
@@ -105,7 +105,7 @@ public class MessageIdReindexingRoutes implements Routes {
     private Route reIndexMessage() {
         return TaskFromRequestRegistry.builder()
             .parameterName(TASK_PARAMETER)
-            .register(ReindexingRoutes.RE_INDEX, request -> reIndexer.reIndex(extractMessageId(request)))
+            .register(MailboxesRoutes.RE_INDEX, request -> reIndexer.reIndex(extractMessageId(request)))
             .buildAsRoute(taskManager);
     }
 
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
index d5e814e..9e040a0 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
@@ -19,17 +19,26 @@
 
 package org.apache.james.webadmin.routes;
 
+import static org.apache.james.webadmin.routes.MailboxesRoutes.RE_INDEX;
+import static org.apache.james.webadmin.routes.MailboxesRoutes.TASK_PARAMETER;
+
 import javax.inject.Inject;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
+import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 
 import org.apache.james.core.Username;
+import org.apache.james.mailbox.indexer.ReIndexer;
+import org.apache.james.mailbox.model.MailboxId;
+import org.apache.james.task.TaskManager;
 import org.apache.james.webadmin.Constants;
 import org.apache.james.webadmin.Routes;
 import org.apache.james.webadmin.service.UserMailboxesService;
+import org.apache.james.webadmin.tasks.TaskFromRequestRegistry;
+import org.apache.james.webadmin.tasks.TaskIdDto;
 import org.apache.james.webadmin.utils.ErrorResponder;
 import org.apache.james.webadmin.utils.ErrorResponder.ErrorType;
 import org.apache.james.webadmin.utils.JsonTransformer;
@@ -47,6 +56,7 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
 import spark.Request;
+import spark.Route;
 import spark.Service;
 
 @Api(tags = "User's Mailbox")
@@ -65,12 +75,18 @@ public class UserMailboxesRoutes implements Routes {
 
     private final UserMailboxesService userMailboxesService;
     private final JsonTransformer jsonTransformer;
+    private final TaskManager taskManager;
+    private final MailboxId.Factory mailboxIdFactory;
+    private final ReIndexer reIndexer;
     private Service service;
 
     @Inject
-    public UserMailboxesRoutes(UserMailboxesService userMailboxesService, JsonTransformer jsonTransformer) {
+    UserMailboxesRoutes(UserMailboxesService userMailboxesService, JsonTransformer jsonTransformer, TaskManager taskManager, MailboxId.Factory mailboxIdFactory, ReIndexer reIndexer) {
         this.userMailboxesService = userMailboxesService;
         this.jsonTransformer = jsonTransformer;
+        this.taskManager = taskManager;
+        this.mailboxIdFactory = mailboxIdFactory;
+        this.reIndexer = reIndexer;
     }
 
     @Override
@@ -91,6 +107,8 @@ public class UserMailboxesRoutes implements Routes {
         defineDeleteUserMailbox();
 
         defineDeleteUserMailboxes();
+
+        service.post(USER_MAILBOXES_BASE, defineReIndexMailboxes(), jsonTransformer);
     }
 
     @GET
@@ -121,6 +139,31 @@ public class UserMailboxesRoutes implements Routes {
         }, jsonTransformer);
     }
 
+    @POST
+    @ApiImplicitParams({
+        @ApiImplicitParam(required = true, dataType = "string", name = "username", paramType = "path"),
+        @ApiImplicitParam(
+            required = true,
+            name = "task",
+            paramType = "query parameter",
+            dataType = "String",
+            defaultValue = "none",
+            example = "?task=reIndex",
+            value = "Compulsory. Only supported value is `reIndex`")
+    })
+    @ApiOperation(value = "Perform an action on a user mailbox")
+    @ApiResponses(value = {
+        @ApiResponse(code = HttpStatus.CREATED_201, message = "Task is created", response = TaskIdDto.class),
+        @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side."),
+        @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Bad request - details in the returned error message")
+    })
+    public Route defineReIndexMailboxes() {
+        return TaskFromRequestRegistry.builder()
+            .parameterName(TASK_PARAMETER)
+            .register(RE_INDEX, request -> reIndexer.reIndex(getUsernameParam(request)))
+            .buildAsRoute(taskManager);
+    }
+
     @DELETE
     @Path("/{mailboxName}")
     @ApiImplicitParams({
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/ReindexingRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
similarity index 71%
rename from server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/ReindexingRoutesTest.java
rename to server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
index 40ab5de..67b0043 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/ReindexingRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
@@ -39,7 +39,6 @@ import org.apache.james.mailbox.MessageManager;
 import org.apache.james.mailbox.indexer.ReIndexer;
 import org.apache.james.mailbox.inmemory.InMemoryId;
 import org.apache.james.mailbox.inmemory.InMemoryMailboxManager;
-import org.apache.james.mailbox.inmemory.InMemoryMessageId;
 import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
 import org.apache.james.mailbox.model.ComposedMessageId;
 import org.apache.james.mailbox.model.Mailbox;
@@ -55,13 +54,10 @@ import org.apache.james.webadmin.service.PreviousReIndexingService;
 import org.apache.james.webadmin.utils.ErrorResponder;
 import org.apache.james.webadmin.utils.JsonTransformer;
 import org.apache.mailbox.tools.indexer.FullReindexingTask;
-import org.apache.mailbox.tools.indexer.MessageIdReIndexerImpl;
-import org.apache.mailbox.tools.indexer.MessageIdReIndexingTask;
 import org.apache.mailbox.tools.indexer.ReIndexerImpl;
 import org.apache.mailbox.tools.indexer.ReIndexerPerformer;
 import org.apache.mailbox.tools.indexer.SingleMailboxReindexingTask;
 import org.apache.mailbox.tools.indexer.SingleMessageReindexingTask;
-import org.apache.mailbox.tools.indexer.UserReindexingTask;
 import org.eclipse.jetty.http.HttpStatus;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
@@ -71,7 +67,7 @@ import org.mockito.ArgumentCaptor;
 
 import io.restassured.RestAssured;
 
-class ReindexingRoutesTest {
+class MailboxesRoutesTest {
     private static final Username USERNAME = Username.of("benwa@apache.org");
     private static final MailboxPath INBOX = MailboxPath.inbox(USERNAME);
 
@@ -97,15 +93,11 @@ class ReindexingRoutesTest {
 
         webAdminServer = WebAdminUtils.createWebAdminServer(
                 new TasksRoutes(taskManager, jsonTransformer),
-                new ReindexingRoutes(
+                new MailboxesRoutes(
                     taskManager,
                     new PreviousReIndexingService(taskManager),
                     mailboxIdFactory,
                     reIndexer,
-                    jsonTransformer),
-                new MessageIdReindexingRoutes(taskManager,
-                    new InMemoryMessageId.Factory(),
-                    new MessageIdReIndexerImpl(reIndexerPerformer),
                     jsonTransformer))
             .start();
 
@@ -275,195 +267,6 @@ class ReindexingRoutesTest {
     }
 
     @Nested
-    class UserReprocessing {
-        @Nested
-        class Validation {
-            @Test
-            void userReprocessingShouldFailWithNoTask() {
-                given()
-                    .queryParam("user", USERNAME.asString())
-                .when()
-                    .post("/mailboxes")
-                .then()
-                    .statusCode(HttpStatus.BAD_REQUEST_400)
-                    .body("statusCode", is(400))
-                    .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
-                    .body("message", is("Invalid arguments supplied in the user request"))
-                    .body("details", is("'task' query parameter is compulsory. Supported values are [reIndex]"));
-            }
-
-            @Test
-            void userReprocessingShouldFailWithBadTask() {
-                given()
-                    .queryParam("user", USERNAME.asString())
-                    .queryParam("task", "bad")
-                .when()
-                    .post("/mailboxes")
-                .then()
-                    .statusCode(HttpStatus.BAD_REQUEST_400)
-                    .body("statusCode", is(400))
-                    .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
-                    .body("message", is("Invalid arguments supplied in the user request"))
-                    .body("details", is("Invalid value supplied for query parameter 'task': bad. Supported values are [reIndex]"));
-            }
-
-            @Test
-            void userReprocessingShouldFailWithBadUser() {
-                given()
-                    .queryParam("user", "bad@bad@bad")
-                    .queryParam("task", "reIndex")
-                .when()
-                    .post("/mailboxes")
-                .then()
-                    .statusCode(HttpStatus.BAD_REQUEST_400)
-                    .body("statusCode", is(400))
-                    .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
-                    .body("message", is("Error while parsing 'user'"));
-            }
-        }
-
-        @Nested
-        class TaskDetails {
-            @Test
-            void userReprocessingShouldNotFailWhenNoMail() {
-                String taskId = given()
-                    .queryParam("user", USERNAME.asString())
-                    .queryParam("task", "reIndex")
-                .when()
-                    .post("/mailboxes")
-                    .jsonPath()
-                    .get("taskId");
-
-                given()
-                    .basePath(TasksRoutes.BASE)
-                .when()
-                    .get(taskId + "/await")
-                .then()
-                    .body("status", is("completed"))
-                    .body("taskId", is(notNullValue()))
-                    .body("type", is(UserReindexingTask.USER_RE_INDEXING.asString()))
-                    .body("additionalInformation.username", is("benwa@apache.org"))
-                    .body("additionalInformation.successfullyReprocessedMailCount", is(0))
-                    .body("additionalInformation.failedReprocessedMailCount", is(0))
-                    .body("startedDate", is(notNullValue()))
-                    .body("submitDate", is(notNullValue()))
-                    .body("completedDate", is(notNullValue()));
-            }
-
-            @Test
-            void userReprocessingShouldReturnTaskDetailsWhenMail() throws Exception {
-                MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
-                mailboxManager.createMailbox(INBOX, systemSession).get();
-                mailboxManager.getMailbox(INBOX, systemSession)
-                    .appendMessage(
-                        MessageManager.AppendCommand.builder().build("header: value\r\n\r\nbody"),
-                        systemSession);
-
-                String taskId = given()
-                    .queryParam("user", USERNAME.asString())
-                    .queryParam("task", "reIndex")
-                .when()
-                    .post("/mailboxes")
-                    .jsonPath()
-                    .get("taskId");
-
-                given()
-                    .basePath(TasksRoutes.BASE)
-                .when()
-                    .get(taskId + "/await")
-                .then()
-                    .body("status", is("completed"))
-                    .body("taskId", is(notNullValue()))
-                    .body("type", is(UserReindexingTask.USER_RE_INDEXING.asString()))
-                    .body("additionalInformation.username", is("benwa@apache.org"))
-                    .body("additionalInformation.successfullyReprocessedMailCount", is(1))
-                    .body("additionalInformation.failedReprocessedMailCount", is(0))
-                    .body("startedDate", is(notNullValue()))
-                    .body("submitDate", is(notNullValue()))
-                    .body("completedDate", is(notNullValue()));
-            }
-
-            @Test
-            void userReprocessingShouldReturnTaskDetailsWhenFailing() throws Exception {
-                MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
-                MailboxId mailboxId = mailboxManager.createMailbox(INBOX, systemSession).get();
-                ComposedMessageId composedMessageId = mailboxManager.getMailbox(INBOX, systemSession)
-                    .appendMessage(
-                        MessageManager.AppendCommand.builder().build("header: value\r\n\r\nbody"),
-                        systemSession);
-
-                doThrow(new RuntimeException())
-                    .when(searchIndex)
-                    .add(any(MailboxSession.class), any(Mailbox.class), any(MailboxMessage.class));
-
-                String taskId = with()
-                    .queryParam("user", USERNAME.asString())
-                    .queryParam("task", "reIndex")
-                    .post("/mailboxes")
-                    .jsonPath()
-                    .get("taskId");
-
-                long uidAsLong = composedMessageId.getUid().asLong();
-                given()
-                    .basePath(TasksRoutes.BASE)
-                .when()
-                    .get(taskId + "/await")
-                .then()
-                    .body("status", is("failed"))
-                    .body("taskId", is(notNullValue()))
-                    .body("type", is(UserReindexingTask.USER_RE_INDEXING.asString()))
-                    .body("additionalInformation.successfullyReprocessedMailCount", is(0))
-                    .body("additionalInformation.failedReprocessedMailCount", is(1))
-                    .body("additionalInformation.failures.\"" + mailboxId.serialize() + "\"[0].uid", is(Long.valueOf(uidAsLong).intValue()))
-                    .body("startedDate", is(notNullValue()))
-                    .body("submitDate", is(notNullValue()));
-            }
-        }
-
-        @Nested
-        class SideEffects {
-            @Test
-            void userReprocessingShouldPerformReprocessingWhenMail() throws Exception {
-                MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
-                MailboxId mailboxId = mailboxManager.createMailbox(INBOX, systemSession).get();
-                ComposedMessageId createdMessage = mailboxManager.getMailbox(INBOX, systemSession)
-                    .appendMessage(
-                        MessageManager.AppendCommand.builder().build("header: value\r\n\r\nbody"),
-                        systemSession);
-
-                String taskId = given()
-                    .queryParam("user", USERNAME.asString())
-                    .queryParam("task", "reIndex")
-                .when()
-                    .post("/mailboxes")
-                    .jsonPath()
-                    .get("taskId");
-
-                given()
-                    .basePath(TasksRoutes.BASE)
-                .when()
-                    .get(taskId + "/await")
-                .then()
-                    .body("status", is("completed"));
-
-
-                ArgumentCaptor<MailboxMessage> messageCaptor = ArgumentCaptor.forClass(MailboxMessage.class);
-                ArgumentCaptor<MailboxId> mailboxIdCaptor = ArgumentCaptor.forClass(MailboxId.class);
-                ArgumentCaptor<Mailbox> mailboxCaptor2 = ArgumentCaptor.forClass(Mailbox.class);
-
-                verify(searchIndex).deleteAll(any(MailboxSession.class), mailboxIdCaptor.capture());
-                verify(searchIndex).add(any(MailboxSession.class), mailboxCaptor2.capture(), messageCaptor.capture());
-                verifyNoMoreInteractions(searchIndex);
-
-                assertThat(mailboxIdCaptor.getValue()).matches(capturedMailboxId -> capturedMailboxId.equals(mailboxId));
-                assertThat(mailboxCaptor2.getValue()).matches(mailbox -> mailbox.getMailboxId().equals(mailboxId));
-                assertThat(messageCaptor.getValue()).matches(message -> message.getMailboxId().equals(mailboxId)
-                    && message.getUid().equals(createdMessage.getUid()));
-            }
-        }
-    }
-
-    @Nested
     class MailboxReprocessing {
         @Nested
         class Validation {
@@ -818,137 +621,6 @@ class ReindexingRoutesTest {
     }
 
     @Nested
-    class MessageIdReprocessing {
-        @Nested
-        class Validation {
-            @Test
-            void messageIdReprocessingShouldFailWithNoTask() {
-                when()
-                    .post("/messages/7")
-                .then()
-                    .statusCode(HttpStatus.BAD_REQUEST_400)
-                    .body("statusCode", is(400))
-                    .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
-                    .body("message", is("Invalid arguments supplied in the user request"))
-                    .body("details", is("'task' query parameter is compulsory. Supported values are [reIndex]"));
-            }
-
-            @Test
-            void messageIdReprocessingShouldFailWithBadTask() {
-                when()
-                    .post("/messages/7?task=bad")
-                .then()
-                    .statusCode(HttpStatus.BAD_REQUEST_400)
-                    .body("statusCode", is(400))
-                    .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
-                    .body("message", is("Invalid arguments supplied in the user request"))
-                    .body("details", is("Invalid value supplied for query parameter 'task': bad. Supported values are [reIndex]"));
-            }
-
-            @Test
-            void messageIdReprocessingShouldFailWithBadMessageId() {
-                when()
-                    .post("/messages/bad?task=reIndex")
-                .then()
-                    .statusCode(HttpStatus.BAD_REQUEST_400)
-                    .body("statusCode", is(400))
-                    .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
-                    .body("message", is("Error while parsing 'messageId'"));
-            }
-        }
-
-        @Nested
-        class TaskDetails {
-            @Test
-            void messageIdReprocessingShouldNotFailWhenUidNotFound() {
-                String taskId = when()
-                    .post("/messages/1?task=reIndex")
-                    .jsonPath()
-                    .get("taskId");
-
-                given()
-                    .basePath(TasksRoutes.BASE)
-                .when()
-                    .get(taskId + "/await")
-                .then()
-                    .body("status", is("completed"))
-                    .body("taskId", is(notNullValue()))
-                    .body("type", is(MessageIdReIndexingTask.TYPE.asString()))
-                    .body("additionalInformation.messageId", is("1"))
-                    .body("startedDate", is(notNullValue()))
-                    .body("submitDate", is(notNullValue()))
-                    .body("completedDate", is(notNullValue()));
-            }
-
-            @Test
-            void messageIdReprocessingShouldReturnTaskDetailsWhenMail() throws Exception {
-                MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
-                mailboxManager.createMailbox(INBOX, systemSession).get();
-                ComposedMessageId composedMessageId = mailboxManager.getMailbox(INBOX, systemSession)
-                    .appendMessage(
-                        MessageManager.AppendCommand.builder().build("header: value\r\n\r\nbody"),
-                        systemSession);
-
-                String taskId = when()
-                    .post("/messages/" + composedMessageId.getMessageId().serialize() + "?task=reIndex")
-                    .jsonPath()
-                    .get("taskId");
-
-                given()
-                    .basePath(TasksRoutes.BASE)
-                .when()
-                    .get(taskId + "/await")
-                .then()
-                    .body("status", is("completed"))
-                    .body("taskId", is(notNullValue()))
-                    .body("type", is(MessageIdReIndexingTask.TYPE.asString()))
-                    .body("additionalInformation.messageId", is(composedMessageId.getMessageId().serialize()))
-                    .body("startedDate", is(notNullValue()))
-                    .body("submitDate", is(notNullValue()))
-                    .body("completedDate", is(notNullValue()));
-            }
-        }
-
-        @Nested
-        class SideEffects {
-            @Test
-            void messageIdReprocessingShouldPerformReprocessingWhenMail() throws Exception {
-                MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
-                mailboxManager.createMailbox(INBOX, systemSession).get();
-                ComposedMessageId composedMessageId = mailboxManager.getMailbox(INBOX, systemSession)
-                    .appendMessage(
-                        MessageManager.AppendCommand.builder().build("header: value\r\n\r\nbody"),
-                        systemSession);
-
-                String taskId = when()
-                    .post("/messages/" + composedMessageId.getMessageId().serialize() + "?task=reIndex")
-                    .jsonPath()
-                    .get("taskId");
-
-                given()
-                    .basePath(TasksRoutes.BASE)
-                .when()
-                    .get(taskId + "/await")
-                .then()
-                    .body("status", is("completed"));
-
-
-                ArgumentCaptor<MailboxMessage> messageCaptor = ArgumentCaptor.forClass(MailboxMessage.class);
-                ArgumentCaptor<Mailbox> mailboxCaptor = ArgumentCaptor.forClass(Mailbox.class);
-
-                verify(searchIndex).add(any(MailboxSession.class), mailboxCaptor.capture(), messageCaptor.capture());
-                verifyNoMoreInteractions(searchIndex);
-
-                assertThat(mailboxCaptor.getValue()).matches(mailbox -> mailbox.getMailboxId().equals(composedMessageId.getMailboxId()));
-                assertThat(messageCaptor.getValue()).matches(message -> message.getComposedMessageIdWithMetaData()
-                    .getComposedMessageId()
-                    .getMessageId()
-                    .equals(composedMessageId.getMessageId()));
-            }
-        }
-    }
-
-    @Nested
     class FixingReIndexing {
         @Nested
         class Validation {
@@ -976,30 +648,6 @@ class ReindexingRoutesTest {
             }
 
             @Test
-            void fixingReIndexingShouldThrowOnUserParameter() {
-                String taskId = with()
-                    .post("/mailboxes?task=reIndex")
-                    .jsonPath()
-                    .get("taskId");
-
-                with()
-                    .basePath(TasksRoutes.BASE)
-                    .get(taskId + "/await");
-
-                given()
-                    .queryParam("reIndexFailedMessagesOf", taskId)
-                    .queryParam("task", "reIndex")
-                    .queryParam("user", "bob@domain.tld")
-                .when()
-                    .post("/mailboxes")
-                .then()
-                    .statusCode(HttpStatus.BAD_REQUEST_400)
-                    .body("statusCode", is(400))
-                    .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
-                    .body("message", is("Can not specify 'user' and 'reIndexFailedMessagesOf' query parameters at the same time"));
-            }
-
-            @Test
             void fixingReIndexingShouldFailWithBadTask() {
                 String taskId = with()
                     .post("/mailboxes?task=reIndex")
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MalformedUrlRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MalformedUrlRoutesTest.java
index c9b4e4a..1589fde 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MalformedUrlRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MalformedUrlRoutesTest.java
@@ -35,7 +35,11 @@ import java.nio.charset.StandardCharsets;
 
 import org.apache.james.core.Username;
 import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.indexer.ReIndexer;
+import org.apache.james.mailbox.inmemory.InMemoryId;
 import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
+import org.apache.james.task.Hostname;
+import org.apache.james.task.MemoryTaskManager;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.WebAdminUtils;
@@ -57,8 +61,10 @@ class MalformedUrlRoutesTest {
         usersRepository = mock(UsersRepository.class);
         when(usersRepository.contains(USERNAME)).thenReturn(true);
 
+        MemoryTaskManager taskManager = new MemoryTaskManager(new Hostname("foo"));
         webAdminServer = WebAdminUtils.createWebAdminServer(
-            new UserMailboxesRoutes(new UserMailboxesService(mailboxManager, usersRepository), new JsonTransformer()))
+            new UserMailboxesRoutes(new UserMailboxesService(mailboxManager, usersRepository), new JsonTransformer(),
+                taskManager, new InMemoryId.Factory(), mock(ReIndexer.class)))
             .start();
     }
 
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesTest.java
new file mode 100644
index 0000000..6d068fb
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesTest.java
@@ -0,0 +1,235 @@
+/****************************************************************
+ * 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.webadmin.routes;
+
+import static io.restassured.RestAssured.given;
+import static io.restassured.RestAssured.when;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import org.apache.james.core.Username;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.indexer.ReIndexer;
+import org.apache.james.mailbox.inmemory.InMemoryId;
+import org.apache.james.mailbox.inmemory.InMemoryMailboxManager;
+import org.apache.james.mailbox.inmemory.InMemoryMessageId;
+import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
+import org.apache.james.mailbox.model.ComposedMessageId;
+import org.apache.james.mailbox.model.Mailbox;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex;
+import org.apache.james.task.Hostname;
+import org.apache.james.task.MemoryTaskManager;
+import org.apache.james.webadmin.WebAdminServer;
+import org.apache.james.webadmin.WebAdminUtils;
+import org.apache.james.webadmin.utils.ErrorResponder;
+import org.apache.james.webadmin.utils.JsonTransformer;
+import org.apache.mailbox.tools.indexer.MessageIdReIndexerImpl;
+import org.apache.mailbox.tools.indexer.MessageIdReIndexingTask;
+import org.apache.mailbox.tools.indexer.ReIndexerImpl;
+import org.apache.mailbox.tools.indexer.ReIndexerPerformer;
+import org.eclipse.jetty.http.HttpStatus;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+
+import io.restassured.RestAssured;
+
+class MessageRoutesTest {
+    private static final Username USERNAME = Username.of("benwa@apache.org");
+    private static final MailboxPath INBOX = MailboxPath.inbox(USERNAME);
+
+    private WebAdminServer webAdminServer;
+    private ListeningMessageSearchIndex searchIndex;
+    private InMemoryMailboxManager mailboxManager;
+
+    @BeforeEach
+    void beforeEach() {
+        mailboxManager = InMemoryIntegrationResources.defaultResources().getMailboxManager();
+        MemoryTaskManager taskManager = new MemoryTaskManager(new Hostname("foo"));
+        InMemoryId.Factory mailboxIdFactory = new InMemoryId.Factory();
+        searchIndex = mock(ListeningMessageSearchIndex.class);
+        ReIndexerPerformer reIndexerPerformer = new ReIndexerPerformer(
+            mailboxManager,
+            searchIndex,
+            mailboxManager.getMapperFactory());
+        ReIndexer reIndexer = new ReIndexerImpl(
+            reIndexerPerformer,
+            mailboxManager,
+            mailboxManager.getMapperFactory());
+        JsonTransformer jsonTransformer = new JsonTransformer();
+
+        webAdminServer = WebAdminUtils.createWebAdminServer(
+                new TasksRoutes(taskManager, jsonTransformer),
+                new MessagesRoutes(taskManager,
+                    new InMemoryMessageId.Factory(),
+                    new MessageIdReIndexerImpl(reIndexerPerformer),
+                    jsonTransformer))
+            .start();
+
+        RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminServer).build();
+        RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
+    }
+
+    @AfterEach
+    void tearDown() {
+        webAdminServer.destroy();
+    }
+
+    @Nested
+    class MessageReprocessing {
+        @Nested
+        class Validation {
+            @Test
+            void messageIdReprocessingShouldFailWithNoTask() {
+                when()
+                    .post("/messages/7")
+                .then()
+                    .statusCode(HttpStatus.BAD_REQUEST_400)
+                    .body("statusCode", is(400))
+                    .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+                    .body("message", is("Invalid arguments supplied in the user request"))
+                    .body("details", is("'task' query parameter is compulsory. Supported values are [reIndex]"));
+            }
+
+            @Test
+            void messageIdReprocessingShouldFailWithBadTask() {
+                when()
+                    .post("/messages/7?task=bad")
+                .then()
+                    .statusCode(HttpStatus.BAD_REQUEST_400)
+                    .body("statusCode", is(400))
+                    .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+                    .body("message", is("Invalid arguments supplied in the user request"))
+                    .body("details", is("Invalid value supplied for query parameter 'task': bad. Supported values are [reIndex]"));
+            }
+
+            @Test
+            void messageIdReprocessingShouldFailWithBadMessageId() {
+                when()
+                    .post("/messages/bad?task=reIndex")
+                .then()
+                    .statusCode(HttpStatus.BAD_REQUEST_400)
+                    .body("statusCode", is(400))
+                    .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+                    .body("message", is("Error while parsing 'messageId'"));
+            }
+        }
+
+        @Nested
+        class TaskDetails {
+            @Test
+            void messageIdReprocessingShouldNotFailWhenUidNotFound() {
+                String taskId = when()
+                    .post("/messages/1?task=reIndex")
+                    .jsonPath()
+                    .get("taskId");
+
+                given()
+                    .basePath(TasksRoutes.BASE)
+                .when()
+                    .get(taskId + "/await")
+                .then()
+                    .body("status", is("completed"))
+                    .body("taskId", is(notNullValue()))
+                    .body("type", is(MessageIdReIndexingTask.TYPE.asString()))
+                    .body("additionalInformation.messageId", is("1"))
+                    .body("startedDate", is(notNullValue()))
+                    .body("submitDate", is(notNullValue()))
+                    .body("completedDate", is(notNullValue()));
+            }
+
+            @Test
+            void messageIdReprocessingShouldReturnTaskDetailsWhenMail() throws Exception {
+                MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
+                mailboxManager.createMailbox(INBOX, systemSession).get();
+                ComposedMessageId composedMessageId = mailboxManager.getMailbox(INBOX, systemSession)
+                    .appendMessage(
+                        MessageManager.AppendCommand.builder().build("header: value\r\n\r\nbody"),
+                        systemSession);
+
+                String taskId = when()
+                    .post("/messages/" + composedMessageId.getMessageId().serialize() + "?task=reIndex")
+                    .jsonPath()
+                    .get("taskId");
+
+                given()
+                    .basePath(TasksRoutes.BASE)
+                .when()
+                    .get(taskId + "/await")
+                .then()
+                    .body("status", is("completed"))
+                    .body("taskId", is(notNullValue()))
+                    .body("type", is(MessageIdReIndexingTask.TYPE.asString()))
+                    .body("additionalInformation.messageId", is(composedMessageId.getMessageId().serialize()))
+                    .body("startedDate", is(notNullValue()))
+                    .body("submitDate", is(notNullValue()))
+                    .body("completedDate", is(notNullValue()));
+            }
+        }
+
+        @Nested
+        class SideEffects {
+            @Test
+            void messageIdReprocessingShouldPerformReprocessingWhenMail() throws Exception {
+                MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
+                mailboxManager.createMailbox(INBOX, systemSession).get();
+                ComposedMessageId composedMessageId = mailboxManager.getMailbox(INBOX, systemSession)
+                    .appendMessage(
+                        MessageManager.AppendCommand.builder().build("header: value\r\n\r\nbody"),
+                        systemSession);
+
+                String taskId = when()
+                    .post("/messages/" + composedMessageId.getMessageId().serialize() + "?task=reIndex")
+                    .jsonPath()
+                    .get("taskId");
+
+                given()
+                    .basePath(TasksRoutes.BASE)
+                .when()
+                    .get(taskId + "/await")
+                .then()
+                    .body("status", is("completed"));
+
+
+                ArgumentCaptor<MailboxMessage> messageCaptor = ArgumentCaptor.forClass(MailboxMessage.class);
+                ArgumentCaptor<Mailbox> mailboxCaptor = ArgumentCaptor.forClass(Mailbox.class);
+
+                verify(searchIndex).add(any(MailboxSession.class), mailboxCaptor.capture(), messageCaptor.capture());
+                verifyNoMoreInteractions(searchIndex);
+
+                assertThat(mailboxCaptor.getValue()).matches(mailbox -> mailbox.getMailboxId().equals(composedMessageId.getMailboxId()));
+                assertThat(messageCaptor.getValue()).matches(message -> message.getComposedMessageIdWithMetaData()
+                    .getComposedMessageId()
+                    .getMessageId()
+                    .equals(composedMessageId.getMessageId()));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
index dd0d7bf..b33bafb 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
@@ -19,46 +19,64 @@
 
 package org.apache.james.webadmin.routes;
 
+import static io.restassured.RestAssured.given;
 import static io.restassured.RestAssured.when;
 import static io.restassured.RestAssured.with;
 import static org.apache.james.webadmin.Constants.SEPARATOR;
 import static org.apache.james.webadmin.routes.UserMailboxesRoutes.USERS_BASE;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.Matchers.notNullValue;
 import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
 import java.util.List;
 import java.util.Map;
 
 import org.apache.james.core.Username;
-import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MailboxSessionUtil;
+import org.apache.james.mailbox.MessageManager;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MailboxExistsException;
 import org.apache.james.mailbox.exception.MailboxNotFoundException;
+import org.apache.james.mailbox.indexer.ReIndexer;
 import org.apache.james.mailbox.inmemory.InMemoryId;
+import org.apache.james.mailbox.inmemory.InMemoryMailboxManager;
 import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
+import org.apache.james.mailbox.model.ComposedMessageId;
+import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxMetaData;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.search.MailboxQuery;
+import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex;
+import org.apache.james.task.Hostname;
+import org.apache.james.task.MemoryTaskManager;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.WebAdminUtils;
 import org.apache.james.webadmin.service.UserMailboxesService;
+import org.apache.james.webadmin.utils.ErrorResponder;
 import org.apache.james.webadmin.utils.JsonTransformer;
+import org.apache.mailbox.tools.indexer.ReIndexerImpl;
+import org.apache.mailbox.tools.indexer.ReIndexerPerformer;
+import org.apache.mailbox.tools.indexer.UserReindexingTask;
 import org.eclipse.jetty.http.HttpStatus;
+import org.hamcrest.Matchers;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
 
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 
 import io.restassured.RestAssured;
 import io.restassured.http.ContentType;
@@ -66,16 +84,33 @@ import io.restassured.http.ContentType;
 class UserMailboxesRoutesTest {
     private static final Username USERNAME = Username.of("username");
     private static final String MAILBOX_NAME = "myMailboxName";
+    private static final MailboxPath INBOX = MailboxPath.inbox(USERNAME);
 
     private WebAdminServer webAdminServer;
     private UsersRepository usersRepository;
+    private ListeningMessageSearchIndex searchIndex;
 
-    private void createServer(MailboxManager mailboxManager) throws Exception {
+    private void createServer(InMemoryMailboxManager mailboxManager) throws Exception {
         usersRepository = mock(UsersRepository.class);
         when(usersRepository.contains(USERNAME)).thenReturn(true);
 
+
+        MemoryTaskManager taskManager = new MemoryTaskManager(new Hostname("foo"));
+        InMemoryId.Factory mailboxIdFactory = new InMemoryId.Factory();
+        searchIndex = mock(ListeningMessageSearchIndex.class);
+        ReIndexerPerformer reIndexerPerformer = new ReIndexerPerformer(
+            mailboxManager,
+            searchIndex,
+            mailboxManager.getMapperFactory());
+        ReIndexer reIndexer = new ReIndexerImpl(
+            reIndexerPerformer,
+            mailboxManager,
+            mailboxManager.getMapperFactory());
+
         webAdminServer = WebAdminUtils.createWebAdminServer(
-                new UserMailboxesRoutes(new UserMailboxesService(mailboxManager, usersRepository), new JsonTransformer()))
+                new UserMailboxesRoutes(new UserMailboxesService(mailboxManager, usersRepository), new JsonTransformer(),
+                    taskManager, mailboxIdFactory, reIndexer),
+                new TasksRoutes(taskManager, new JsonTransformer()))
             .start();
 
         RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminServer)
@@ -734,12 +769,11 @@ class UserMailboxesRoutesTest {
 
     @Nested
     class ExceptionHandling {
-
-        private MailboxManager mailboxManager;
+        private InMemoryMailboxManager mailboxManager;
 
         @BeforeEach
         void setUp() throws Exception {
-            mailboxManager = mock(MailboxManager.class);
+            mailboxManager = mock(InMemoryMailboxManager.class);
             when(mailboxManager.createSystemSession(any())).thenReturn(MailboxSessionUtil.create(USERNAME));
 
             createServer(mailboxManager);
@@ -992,4 +1026,199 @@ class UserMailboxesRoutesTest {
 
     }
 
+    @Nested
+    class UserReprocessing {
+
+        private InMemoryMailboxManager mailboxManager;
+
+        @BeforeEach
+        void setUp() throws Exception {
+            mailboxManager = InMemoryIntegrationResources.defaultResources().getMailboxManager();
+            createServer(mailboxManager);
+        }
+
+        @Nested
+        class Validation {
+            @Test
+            void userReprocessingShouldFailWithNoTask() {
+                when()
+                    .post()
+                .then()
+                    .statusCode(HttpStatus.BAD_REQUEST_400)
+                    .body("statusCode", Matchers.is(400))
+                    .body("type", Matchers.is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+                    .body("message", Matchers.is("Invalid arguments supplied in the user request"))
+                    .body("details", Matchers.is("'task' query parameter is compulsory. Supported values are [reIndex]"));
+            }
+
+            @Test
+            void userReprocessingShouldFailWithBadTask() {
+                given()
+                    .queryParam("task", "bad")
+                .when()
+                    .post()
+                .then()
+                    .statusCode(HttpStatus.BAD_REQUEST_400)
+                    .body("statusCode", Matchers.is(400))
+                    .body("type", Matchers.is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+                    .body("message", Matchers.is("Invalid arguments supplied in the user request"))
+                    .body("details", Matchers.is("Invalid value supplied for query parameter 'task': bad. Supported values are [reIndex]"));
+            }
+
+            @Test
+            void userReprocessingShouldFailWithBadUser() {
+                RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminServer)
+                    .setBasePath(USERS_BASE + SEPARATOR + "bad@bad@bad" + SEPARATOR + UserMailboxesRoutes.MAILBOXES)
+                    .build();
+
+                given()
+                    .queryParam("user", "bad@bad@bad")
+                    .queryParam("task", "reIndex")
+                .when()
+                    .post()
+                .then()
+                    .statusCode(HttpStatus.BAD_REQUEST_400)
+                    .body("statusCode", Matchers.is(400))
+                    .body("type", Matchers.is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+                    .body("message", Matchers.is("Invalid arguments supplied in the user request"))
+                    .body("details", Matchers.is("The username should not contain multiple domain delimiter."));
+            }
+        }
+
+        @Nested
+        class TaskDetails {
+            @Test
+            void userReprocessingShouldNotFailWhenNoMail() {
+                String taskId = given()
+                    .queryParam("task", "reIndex")
+                .when()
+                    .post()
+                    .jsonPath()
+                    .get("taskId");
+
+                given()
+                    .basePath(TasksRoutes.BASE)
+                    .when()
+                    .get(taskId + "/await")
+                    .then()
+                    .body("status", Matchers.is("completed"))
+                    .body("taskId", Matchers.is(notNullValue()))
+                    .body("type", Matchers.is(UserReindexingTask.USER_RE_INDEXING.asString()))
+                    .body("additionalInformation.username", Matchers.is("username"))
+                    .body("additionalInformation.successfullyReprocessedMailCount", Matchers.is(0))
+                    .body("additionalInformation.failedReprocessedMailCount", Matchers.is(0))
+                    .body("startedDate", Matchers.is(notNullValue()))
+                    .body("submitDate", Matchers.is(notNullValue()))
+                    .body("completedDate", Matchers.is(notNullValue()));
+            }
+
+            @Test
+            void userReprocessingShouldReturnTaskDetailsWhenMail() throws Exception {
+                MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
+                mailboxManager.createMailbox(INBOX, systemSession).get();
+                mailboxManager.getMailbox(INBOX, systemSession)
+                    .appendMessage(
+                        MessageManager.AppendCommand.builder().build("header: value\r\n\r\nbody"),
+                        systemSession);
+
+                String taskId = given()
+                    .queryParam("task", "reIndex")
+                .when()
+                    .post()
+                    .jsonPath()
+                    .get("taskId");
+
+                given()
+                    .basePath(TasksRoutes.BASE)
+                .when()
+                    .get(taskId + "/await")
+                .then()
+                    .body("status", Matchers.is("completed"))
+                    .body("taskId", Matchers.is(notNullValue()))
+                    .body("type", Matchers.is(UserReindexingTask.USER_RE_INDEXING.asString()))
+                    .body("additionalInformation.username", Matchers.is("username"))
+                    .body("additionalInformation.successfullyReprocessedMailCount", Matchers.is(1))
+                    .body("additionalInformation.failedReprocessedMailCount", Matchers.is(0))
+                    .body("startedDate", Matchers.is(notNullValue()))
+                    .body("submitDate", Matchers.is(notNullValue()))
+                    .body("completedDate", Matchers.is(notNullValue()));
+            }
+
+            @Test
+            void userReprocessingShouldReturnTaskDetailsWhenFailing() throws Exception {
+                MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
+                MailboxId mailboxId = mailboxManager.createMailbox(INBOX, systemSession).get();
+                ComposedMessageId composedMessageId = mailboxManager.getMailbox(INBOX, systemSession)
+                    .appendMessage(
+                        MessageManager.AppendCommand.builder().build("header: value\r\n\r\nbody"),
+                        systemSession);
+
+                doThrow(new RuntimeException())
+                    .when(searchIndex)
+                    .add(any(MailboxSession.class), any(Mailbox.class), any(MailboxMessage.class));
+
+                String taskId = with()
+                    .queryParam("task", "reIndex")
+                .post()
+                    .jsonPath()
+                    .get("taskId");
+
+                long uidAsLong = composedMessageId.getUid().asLong();
+                given()
+                    .basePath(TasksRoutes.BASE)
+                .when()
+                    .get(taskId + "/await")
+                .then()
+                    .body("status", Matchers.is("failed"))
+                    .body("taskId", Matchers.is(notNullValue()))
+                    .body("type", Matchers.is(UserReindexingTask.USER_RE_INDEXING.asString()))
+                    .body("additionalInformation.successfullyReprocessedMailCount", Matchers.is(0))
+                    .body("additionalInformation.failedReprocessedMailCount", Matchers.is(1))
+                    .body("additionalInformation.failures.\"" + mailboxId.serialize() + "\"[0].uid", Matchers.is(Long.valueOf(uidAsLong).intValue()))
+                    .body("startedDate", Matchers.is(notNullValue()))
+                    .body("submitDate", Matchers.is(notNullValue()));
+            }
+        }
+
+        @Nested
+        class SideEffects {
+            @Test
+            void userReprocessingShouldPerformReprocessingWhenMail() throws Exception {
+                MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
+                MailboxId mailboxId = mailboxManager.createMailbox(INBOX, systemSession).get();
+                ComposedMessageId createdMessage = mailboxManager.getMailbox(INBOX, systemSession)
+                    .appendMessage(
+                        MessageManager.AppendCommand.builder().build("header: value\r\n\r\nbody"),
+                        systemSession);
+
+                String taskId = given()
+                    .queryParam("task", "reIndex")
+                .when()
+                    .post()
+                    .jsonPath()
+                    .get("taskId");
+
+                given()
+                    .basePath(TasksRoutes.BASE)
+                .when()
+                    .get(taskId + "/await")
+                .then()
+                    .body("status", Matchers.is("completed"));
+
+
+                ArgumentCaptor<MailboxMessage> messageCaptor = ArgumentCaptor.forClass(MailboxMessage.class);
+                ArgumentCaptor<MailboxId> mailboxIdCaptor = ArgumentCaptor.forClass(MailboxId.class);
+                ArgumentCaptor<Mailbox> mailboxCaptor2 = ArgumentCaptor.forClass(Mailbox.class);
+
+                verify(searchIndex).deleteAll(any(MailboxSession.class), mailboxIdCaptor.capture());
+                verify(searchIndex).add(any(MailboxSession.class), mailboxCaptor2.capture(), messageCaptor.capture());
+                verifyNoMoreInteractions(searchIndex);
+
+                assertThat(mailboxIdCaptor.getValue()).matches(capturedMailboxId -> capturedMailboxId.equals(mailboxId));
+                assertThat(mailboxCaptor2.getValue()).matches(mailbox -> mailbox.getMailboxId().equals(mailboxId));
+                assertThat(messageCaptor.getValue()).matches(message -> message.getMailboxId().equals(mailboxId)
+                    && message.getUid().equals(createdMessage.getUid()));
+            }
+        }
+    }
 }
diff --git a/src/site/markdown/server/manage-webadmin.md b/src/site/markdown/server/manage-webadmin.md
index d339699..c3b3786 100644
--- a/src/site/markdown/server/manage-webadmin.md
+++ b/src/site/markdown/server/manage-webadmin.md
@@ -31,6 +31,8 @@ Finally, please note that in case of a malformed URL the 400 bad request respons
  - [HealthCheck](#HealthCheck)
  - [Administrating domains](#Administrating_domains)
  - [Administrating users](#Administrating_users)
+ - [Administrating mailboxes](#Administrating_mailboxes)
+ - [Administrating messages](#Administrating_messages)
  - [Administrating user mailboxes](#Administrating_user_mailboxes)
  - [Administrating quotas by users](#Administrating_quotas_by_users)
  - [Administrating quotas by domains](#Administrating_quotas_by_domains)
@@ -48,7 +50,6 @@ Finally, please note that in case of a malformed URL the 400 bad request respons
  - [Administrating mail queues](#Administrating_mail_queues)
  - [Administrating DLP Configuration](#Administrating_DLP_Configuration)
  - [Administrating Sieve quotas](#Administrating_Sieve_quotas)
- - [ReIndexing](#ReIndexing)
  - [Event Dead Letter](#Event_Dead_Letter)
  - [Deleted Messages Vault](#Deleted_Messages_Vault)
  - [Task management](#Task_management)
@@ -336,6 +337,183 @@ Response codes:
 
  - 200: The user name list was successfully retrieved
 
+## Administrating mailboxes
+
+### All mailboxes
+
+Several actions can be performed on the server mailboxes.
+
+Request pattern is:
+
+```
+curl -XPOST /mailboxes?action=XXX,...
+```
+
+[More details about endpoints returning a task](#Endpoints_returning_a_task).
+
+Response codes:
+
+ - 201: Success. Corresponding task id is returned.
+ - 400: Error in the request. Details can be found in the reported error.
+
+The kind of task scheduled depends on the action parameter. See below for details.
+
+#### ReIndexing action
+
+Be also aware of the limits of this API:
+
+Warning: During the re-indexing, the result of search operations might be altered.
+
+Warning: Canceling this task should be considered unsafe as it will leave the currently reIndexed mailbox as partially indexed.
+
+Warning: While we have been trying to reduce the inconsistency window to a maximum (by keeping track of ongoing events),
+concurrent changes done during the reIndexing might be ignored.
+
+The following actions can be performed:
+ - [ReIndexing all mails](#ReIndexing_all_mails)
+ - [Fixing previously failed ReIndexing](#Fixing_previously_failed_ReIndexing)
+
+##### ReIndexing all mails
+
+```
+curl -XPOST http://ip:port/mailboxes?task=reIndex
+```
+
+Will schedule a task for reIndexing all the mails stored on this James server.
+
+The scheduled task will have the following type `full-reindexing` and the following `additionalInformation`:
+
+```
+{
+  "successfullyReprocessedMailCount":18,
+  "failedReprocessedMailCount": 3,
+  "failures": {
+    "mbx1": [{"uid": 35}, {"uid": 45}],
+    "mbx2": [{"uid": 38}]
+  }
+}
+```
+
+##### Fixing previously failed ReIndexing
+
+Given `bbdb69c9-082a-44b0-a85a-6e33e74287a5` being a taskId generated for a reIndexing tasks
+
+```
+curl -XPOST http://ip:port/mailboxes?task=reIndex&reIndexFailedMessagesOf=bbdb69c9-082a-44b0-a85a-6e33e74287a5
+```
+
+The scheduled task will have the following type `error-recovery-indexation` and the following `additionalInformation`:
+
+```
+{
+  "successfullyReprocessedMailCount":18,
+  "failedReprocessedMailCount": 3,
+  "failures": {
+    "mbx1": [{"uid": 35}, {"uid": 45}],
+    "mbx2": [{"uid": 38}]
+  }
+}
+```
+
+### Single mailbox
+
+#### ReIndexing a mailbox mails
+
+```
+curl -XPOST http://ip:port/mailboxes/{mailboxId}?task=reIndex
+```
+
+Will schedule a task for reIndexing all the mails in one mailbox.
+
+Note that 'mailboxId' path parameter needs to be a (implementation dependent) valid mailboxId.
+
+[More details about endpoints returning a task](#Endpoints_returning_a_task).
+
+Response codes:
+
+ - 201: Success. Corresponding task id is returned.
+ - 400: Error in the request. Details can be found in the reported error.
+
+The scheduled task will have the following type `mailbox-reindexing` and the following `additionalInformation`:
+
+```
+{
+  "mailboxId":"{mailboxId}",
+  "successfullyReprocessedMailCount":18,
+  "failedReprocessedMailCount": 3,
+  "failures": {
+    "mbx1": [{"uid": 35}, {"uid": 45}],
+    "mbx2": [{"uid": 38}]
+  }
+}
+```
+
+Warning: During the re-indexing, the result of search operations might be altered.
+
+Warning: Canceling this task should be considered unsafe as it will leave the currently reIndexed mailbox as partially indexed.
+
+Warning: While we have been trying to reduce the inconsistency window to a maximum (by keeping track of ongoing events),
+concurrent changes done during the reIndexing might be ignored.
+
+#### ReIndexing a single mail
+
+```
+curl -XPOST http://ip:port/mailboxes/{mailboxId}/uid/36?task=reIndex
+```
+
+Will schedule a task for reIndexing a single email.
+
+Note that 'mailboxId' path parameter needs to be a (implementation dependent) valid mailboxId.
+
+[More details about endpoints returning a task](#Endpoints_returning_a_task).
+
+Response codes:
+
+ - 201: Success. Corresponding task id is returned.
+ - 400: Error in the request. Details can be found in the reported error.
+
+The scheduled task will have the following type `message-reindexing` and the following `additionalInformation`:
+
+```
+{
+  "mailboxId":"{mailboxId}",
+  "uid":18
+}
+```
+
+Warning: During the re-indexing, the result of search operations might be altered.
+
+Warning: Canceling this task should be considered unsafe as it will leave the currently reIndexed mailbox as partially indexed.
+
+## Administrating Messages
+
+### ReIndexing a single mail by messageId
+
+```
+curl -XPOST http://ip:port/messages/{messageId}?task=reIndex
+```
+
+Will schedule a task for reIndexing a single email in all the mailboxes containing it.
+
+Note that 'messageId' path parameter needs to be a (implementation dependent) valid messageId.
+
+[More details about endpoints returning a task](#Endpoints_returning_a_task).
+
+Response codes:
+
+ - 201: Success. Corresponding task id is returned.
+ - 400: Error in the request. Details can be found in the reported error.
+
+The scheduled task will have the following type `messageId-reindexing` and the following `additionalInformation`:
+
+```
+{
+  "messageId":"18"
+}
+```
+
+Warning: During the re-indexing, the result of search operations might be altered.
+
 ## Administrating user mailboxes
 
  - [Creating a mailbox](#Creating_a_mailbox)
@@ -343,6 +521,7 @@ Response codes:
  - [Testing existence of a mailbox](#Testing_existence_of_a_mailbox)
  - [Listing user mailboxes](#Listing_user_mailboxes)
  - [Deleting_user_mailboxes](#Deleting_user_mailboxes)
+ - [ReIndexing a user mails](#ReIndexing_a_user_mails)
 
 ### Creating a mailbox
 
@@ -427,6 +606,42 @@ Response codes:
  - 204: The user do not have mailboxes anymore
  - 404: The user name does not exist
 
+### ReIndexing a user mails
+ 
+```
+curl -XPOST http://ip:port/users/usernameToBeUsed/mailboxes?task=reIndex
+```
+
+Will schedule a task for reIndexing all the mails in "bob@domain.com" mailboxes (encoded above).
+ 
+[More details about endpoints returning a task](#Endpoints_returning_a_task).
+ 
+Response codes:
+ 
+ - 201: Success. Corresponding task id is returned.
+ - 400: Error in the request. Details can be found in the reported error.
+
+The scheduled task will have the following type `user-reindexing` and the following `additionalInformation`:
+
+```
+{
+  "user":"bob@domain.com",
+  "successfullyReprocessedMailCount":18,
+  "failedReprocessedMailCount": 3,
+  "failures": {
+    "mbx1": [{"uid": 35}, {"uid": 45}],
+    "mbx2": [{"uid": 38}]
+  }
+}
+```
+
+Warning: During the re-indexing, the result of search operations might be altered.
+
+Warning: Canceling this task should be considered unsafe as it will leave the currently reIndexed mailbox as partially indexed.
+
+Warning: While we have been trying to reduce the inconsistency window to a maximum (by keeping track of ongoing events),
+concurrent changes done during the reIndexing might be ignored.
+
 ## Administrating quotas by users
 
  - [Getting the quota for a user](#Getting_the_quota_for_a_user)
@@ -2500,220 +2715,6 @@ curl -XDELETE http://ip:port/sieve/quota/users/user@domain.com
 Response codes:
  - 204: Operation succeeded
 
-
-## ReIndexing
-
- - [ReIndexing all mails](#ReIndexing_all_mails)
- - [ReIndexing a user mails](#ReIndexing_a_user_mails)
- - [ReIndexing a mailbox mails](#ReIndexing_a_mailbox_mails)
- - [ReIndexing a single mail](#ReIndexing_a_single_mail)
- - [ReIndexing a single mail by messageId](#ReIndexing_a_single_mail_by_messageId)
-
-Be also aware of the limits of these APIs:
-
-Warning: During the re-indexing, the result of search operations might be altered.
-
-Warning: Canceling this task should be considered unsafe as it will leave the currently reIndexed mailbox as partially indexed.
-
-Warning: While we have been trying to reduce the inconsistency window to a maximum (by keeping track of ongoing events),
-concurrent changes done during the reIndexing might be ignored.
-
-### ReIndexing all mails
-
-```
-curl -XPOST http://ip:port/mailboxes?task=reIndex
-```
-
-Will schedule a task for reIndexing all the mails stored on this James server.
-
-[More details about endpoints returning a task](#Endpoints_returning_a_task).
-
-Response codes:
-
- - 201: Task generation succeeded. Corresponding task id is returned.
- - 400: Error in the request. Details can be found in the reported error.
-
-The scheduled task will have the following type `full-reindexing` and the following `additionalInformation`:
-
-```
-{
-  "successfullyReprocessedMailCount":18,
-  "failedReprocessedMailCount": 3,
-  "failures": {
-    "mbx1": [{"uid": 35}, {"uid": 45}],
-    "mbx2": [{"uid": 38}]
-  }
-}
-```
-
-Warning: During the re-indexing, the result of search operations might be altered.
-
-Warning: Canceling this task should be considered unsafe as it will leave the currently reIndexed mailbox as partially indexed.
-
-Warning: While we have been trying to reduce the inconsistency window to a maximum (by keeping track of ongoing events),
-concurrent changes done during the reIndexing might be ignored.
-
-### ReIndexing a user mails
-
-```
-curl -XPOST http://ip:port/mailboxes?task=reIndex,user=bob%40domain.com
-```
-
-Will schedule a task for reIndexing all the mails in "bob@domain.com" mailboxes (encoded above).
-
-[More details about endpoints returning a task](#Endpoints_returning_a_task).
-
-Response codes:
-
- - 201: Task generation succeeded. Corresponding task id is returned.
- - 400: Error in the request. Details can be found in the reported error.
-
-The scheduled task will have the following type `user-reindexing` and the following `additionalInformation`:
-
-```
-{
-  "user":"bob@domain.com",
-  "successfullyReprocessedMailCount":18,
-  "failedReprocessedMailCount": 3,
-  "failures": {
-    "mbx1": [{"uid": 35}, {"uid": 45}],
-    "mbx2": [{"uid": 38}]
-  }
-}
-```
-
-Warning: During the re-indexing, the result of search operations might be altered.
-
-Warning: Canceling this task should be considered unsafe as it will leave the currently reIndexed mailbox as partially indexed.
-
-Warning: While we have been trying to reduce the inconsistency window to a maximum (by keeping track of ongoing events),
-concurrent changes done during the reIndexing might be ignored.
-
-### ReIndexing a mailbox mails
-
-```
-curl -XPOST http://ip:port/mailboxes/{mailboxId}?task=reIndex
-```
-
-Will schedule a task for reIndexing all the mails in one mailbox.
-
-Note that 'mailboxId' path parameter needs to be a (implementation dependent) valid mailboxId.
-
-[More details about endpoints returning a task](#Endpoints_returning_a_task).
-
-Response codes:
-
- - 201: Task generation succeeded. Corresponding task id is returned.
- - 400: Error in the request. Details can be found in the reported error.
-
-The scheduled task will have the following type `mailbox-reindexing` and the following `additionalInformation`:
-
-```
-{
-  "mailboxId":"{mailboxId}",
-  "successfullyReprocessedMailCount":18,
-  "failedReprocessedMailCount": 3,
-  "failures": {
-    "mbx1": [{"uid": 35}, {"uid": 45}],
-    "mbx2": [{"uid": 38}]
-  }
-}
-```
-
-Warning: During the re-indexing, the result of search operations might be altered.
-
-Warning: Canceling this task should be considered unsafe as it will leave the currently reIndexed mailbox as partially indexed.
-
-Warning: While we have been trying to reduce the inconsistency window to a maximum (by keeping track of ongoing events),
-concurrent changes done during the reIndexing might be ignored.
-
-### Fixing previously failed ReIndexing
-
-Given `bbdb69c9-082a-44b0-a85a-6e33e74287a5` being a taskId generated for a reIndexing tasks
-
-```
-curl -XPOST http://ip:port/mailboxes?task=reIndex&reIndexFailedMessagesOf=bbdb69c9-082a-44b0-a85a-6e33e74287a5
-```
-
-Will schedule a task for reIndexing all the mails that this task failed to reIndex.
-
-[More details about endpoints returning a task](#Endpoints_returning_a_task).
-
-Response codes:
-
- - 201: Task generation succeeded. Corresponding task id is returned.
- - 400: Error in the request. Details can be found in the reported error.
-
-The scheduled task will have the following type `error-recovery-indexation` and the following `additionalInformation`:
-
-```
-{
-  "successfullyReprocessedMailCount":18,
-  "failedReprocessedMailCount": 3,
-  "failures": {
-    "mbx1": [{"uid": 35}, {"uid": 45}],
-    "mbx2": [{"uid": 38}]
-  }
-}
-```
-
-### ReIndexing a single mail
-
-```
-curl -XPOST http://ip:port/mailboxes/{mailboxId}/uid/36?task=reIndex
-```
-
-Will schedule a task for reIndexing a single email.
-
-Note that 'mailboxId' path parameter needs to be a (implementation dependent) valid mailboxId.
-
-[More details about endpoints returning a task](#Endpoints_returning_a_task).
-
-Response codes:
-
- - 201: Task generation succeeded. Corresponding task id is returned.
- - 400: Error in the request. Details can be found in the reported error.
-
-The scheduled task will have the following type `message-reindexing` and the following `additionalInformation`:
-
-```
-{
-  "mailboxId":"{mailboxId}",
-  "uid":18
-}
-```
-
-Warning: During the re-indexing, the result of search operations might be altered.
-
-Warning: Canceling this task should be considered unsafe as it will leave the currently reIndexed mailbox as partially indexed.
-
-### ReIndexing a single mail by messageId
-
-```
-curl -XPOST http://ip:port/messages/{messageId}?task=reIndex
-```
-
-Will schedule a task for reIndexing a single email in all the mailboxes containing it.
-
-Note that 'messageId' path parameter needs to be a (implementation dependent) valid messageId.
-
-[More details about endpoints returning a task](#Endpoints_returning_a_task).
-
-Response codes:
-
- - 201: Task generation succeeded. Corresponding task id is returned.
- - 400: Error in the request. Details can be found in the reported error.
-
-The scheduled task will have the following type `messageId-reindexing` and the following `additionalInformation`:
-
-```
-{
-  "messageId":"18"
-}
-```
-
-Warning: During the re-indexing, the result of search operations might be altered.
-
 ## Event Dead Letter
 
 The EventBus allows to register 'group listeners' that are called in a (potentially) distributed fashion. These group


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


[james-project] 03/06: JAMES-2993 Not stopping MemoryTaskManager results in deadlock

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

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

commit 44175bfbbfabd50eee4d7db79b906be216796f7f
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Dec 16 19:27:12 2019 +0700

    JAMES-2993 Not stopping MemoryTaskManager results in deadlock
    
    This results in Reactor boundedElastic thread exaustion
---
 .../james/webadmin/routes/MailboxesRoutesTest.java |  4 +++-
 .../james/webadmin/routes/MessageRoutesTest.java   | 12 +++--------
 .../webadmin/routes/UserMailboxesRoutesTest.java   | 24 +++++++++++++---------
 3 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
index 67b0043..5f0a977 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
@@ -74,11 +74,12 @@ class MailboxesRoutesTest {
     private WebAdminServer webAdminServer;
     private ListeningMessageSearchIndex searchIndex;
     private InMemoryMailboxManager mailboxManager;
+    private MemoryTaskManager taskManager;
 
     @BeforeEach
     void beforeEach() {
         mailboxManager = InMemoryIntegrationResources.defaultResources().getMailboxManager();
-        MemoryTaskManager taskManager = new MemoryTaskManager(new Hostname("foo"));
+        taskManager = new MemoryTaskManager(new Hostname("foo"));
         InMemoryId.Factory mailboxIdFactory = new InMemoryId.Factory();
         searchIndex = mock(ListeningMessageSearchIndex.class);
         ReIndexerPerformer reIndexerPerformer = new ReIndexerPerformer(
@@ -108,6 +109,7 @@ class MailboxesRoutesTest {
     @AfterEach
     void tearDown() {
         webAdminServer.destroy();
+        taskManager.stop();
     }
 
     @Nested
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesTest.java
index 6d068fb..46ef7e6 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesTest.java
@@ -32,8 +32,6 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
 import org.apache.james.core.Username;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageManager;
-import org.apache.james.mailbox.indexer.ReIndexer;
-import org.apache.james.mailbox.inmemory.InMemoryId;
 import org.apache.james.mailbox.inmemory.InMemoryMailboxManager;
 import org.apache.james.mailbox.inmemory.InMemoryMessageId;
 import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
@@ -50,7 +48,6 @@ import org.apache.james.webadmin.utils.ErrorResponder;
 import org.apache.james.webadmin.utils.JsonTransformer;
 import org.apache.mailbox.tools.indexer.MessageIdReIndexerImpl;
 import org.apache.mailbox.tools.indexer.MessageIdReIndexingTask;
-import org.apache.mailbox.tools.indexer.ReIndexerImpl;
 import org.apache.mailbox.tools.indexer.ReIndexerPerformer;
 import org.eclipse.jetty.http.HttpStatus;
 import org.junit.jupiter.api.AfterEach;
@@ -68,21 +65,17 @@ class MessageRoutesTest {
     private WebAdminServer webAdminServer;
     private ListeningMessageSearchIndex searchIndex;
     private InMemoryMailboxManager mailboxManager;
+    private MemoryTaskManager taskManager;
 
     @BeforeEach
     void beforeEach() {
+        taskManager = new MemoryTaskManager(new Hostname("foo"));
         mailboxManager = InMemoryIntegrationResources.defaultResources().getMailboxManager();
-        MemoryTaskManager taskManager = new MemoryTaskManager(new Hostname("foo"));
-        InMemoryId.Factory mailboxIdFactory = new InMemoryId.Factory();
         searchIndex = mock(ListeningMessageSearchIndex.class);
         ReIndexerPerformer reIndexerPerformer = new ReIndexerPerformer(
             mailboxManager,
             searchIndex,
             mailboxManager.getMapperFactory());
-        ReIndexer reIndexer = new ReIndexerImpl(
-            reIndexerPerformer,
-            mailboxManager,
-            mailboxManager.getMapperFactory());
         JsonTransformer jsonTransformer = new JsonTransformer();
 
         webAdminServer = WebAdminUtils.createWebAdminServer(
@@ -100,6 +93,7 @@ class MessageRoutesTest {
     @AfterEach
     void tearDown() {
         webAdminServer.destroy();
+        taskManager.stop();
     }
 
     @Nested
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
index b33bafb..c73e71e 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
@@ -39,6 +39,7 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.james.core.Username;
+import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MailboxSessionUtil;
 import org.apache.james.mailbox.MessageManager;
@@ -55,6 +56,7 @@ import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxMetaData;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.search.MailboxQuery;
+import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
 import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex;
 import org.apache.james.task.Hostname;
@@ -89,23 +91,23 @@ class UserMailboxesRoutesTest {
     private WebAdminServer webAdminServer;
     private UsersRepository usersRepository;
     private ListeningMessageSearchIndex searchIndex;
+    private MemoryTaskManager taskManager;
 
-    private void createServer(InMemoryMailboxManager mailboxManager) throws Exception {
+    private void createServer(MailboxManager mailboxManager, MailboxSessionMapperFactory mapperFactory) throws Exception {
         usersRepository = mock(UsersRepository.class);
         when(usersRepository.contains(USERNAME)).thenReturn(true);
 
 
-        MemoryTaskManager taskManager = new MemoryTaskManager(new Hostname("foo"));
-        InMemoryId.Factory mailboxIdFactory = new InMemoryId.Factory();
+        taskManager = new MemoryTaskManager(new Hostname("foo"));
         searchIndex = mock(ListeningMessageSearchIndex.class);
         ReIndexerPerformer reIndexerPerformer = new ReIndexerPerformer(
             mailboxManager,
             searchIndex,
-            mailboxManager.getMapperFactory());
+            mapperFactory);
         ReIndexer reIndexer = new ReIndexerImpl(
             reIndexerPerformer,
             mailboxManager,
-            mailboxManager.getMapperFactory());
+            mapperFactory);
 
         webAdminServer = WebAdminUtils.createWebAdminServer(
                 new UserMailboxesRoutes(new UserMailboxesService(mailboxManager, usersRepository), new JsonTransformer(),
@@ -121,6 +123,7 @@ class UserMailboxesRoutesTest {
     @AfterEach
     void tearDown() {
         webAdminServer.destroy();
+        taskManager.stop();
     }
 
     @Nested
@@ -128,7 +131,8 @@ class UserMailboxesRoutesTest {
 
         @BeforeEach
         void setUp() throws Exception {
-            createServer(InMemoryIntegrationResources.defaultResources().getMailboxManager());
+            InMemoryMailboxManager mailboxManager = InMemoryIntegrationResources.defaultResources().getMailboxManager();
+            createServer(mailboxManager, mailboxManager.getMapperFactory());
         }
 
         @Test
@@ -769,14 +773,14 @@ class UserMailboxesRoutesTest {
 
     @Nested
     class ExceptionHandling {
-        private InMemoryMailboxManager mailboxManager;
+        private MailboxManager mailboxManager;
 
         @BeforeEach
         void setUp() throws Exception {
-            mailboxManager = mock(InMemoryMailboxManager.class);
+            mailboxManager = mock(MailboxManager.class);
             when(mailboxManager.createSystemSession(any())).thenReturn(MailboxSessionUtil.create(USERNAME));
 
-            createServer(mailboxManager);
+            createServer(mailboxManager, mock(MailboxSessionMapperFactory.class));
         }
 
         @Test
@@ -1034,7 +1038,7 @@ class UserMailboxesRoutesTest {
         @BeforeEach
         void setUp() throws Exception {
             mailboxManager = InMemoryIntegrationResources.defaultResources().getMailboxManager();
-            createServer(mailboxManager);
+            createServer(mailboxManager, mailboxManager.getMapperFactory());
         }
 
         @Nested


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