JAMES-2555 Add webAdmin MessageIdReindexing routes
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/54fcdf39 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/54fcdf39 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/54fcdf39 Branch: refs/heads/master Commit: 54fcdf3908631c3fcfce1f5e08f884401d884c2f Parents: dead91f Author: Benoit Tellier <btell...@linagora.com> Authored: Mon Oct 15 11:38:39 2018 +0700 Committer: Benoit Tellier <btell...@linagora.com> Committed: Tue Oct 23 08:43:46 2018 +0700 ---------------------------------------------------------------------- .../routes/MessageIdReindexingRoutes.java | 94 +++++++++++++ .../webadmin/routes/ReIndexingRoutesUtil.java | 38 ++++++ .../james/webadmin/routes/ReindexingRoutes.java | 15 +-- .../webadmin/routes/ReindexingRoutesTest.java | 134 +++++++++++++++++++ 4 files changed, 268 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/54fcdf39/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MessageIdReindexingRoutes.java ---------------------------------------------------------------------- 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/MessageIdReindexingRoutes.java new file mode 100644 index 0000000..1e73945 --- /dev/null +++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MessageIdReindexingRoutes.java @@ -0,0 +1,94 @@ +/**************************************************************** + * 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 org.apache.james.webadmin.routes.ReindexingRoutes.BASE_PATH; + +import javax.inject.Inject; + +import org.apache.james.mailbox.indexer.MessageIdReIndexer; +import org.apache.james.mailbox.model.MessageId; +import org.apache.james.task.Task; +import org.apache.james.task.TaskId; +import org.apache.james.task.TaskManager; +import org.apache.james.webadmin.Routes; +import org.apache.james.webadmin.dto.TaskIdDto; +import org.apache.james.webadmin.utils.ErrorResponder; +import org.apache.james.webadmin.utils.JsonTransformer; +import org.eclipse.jetty.http.HttpStatus; + +import com.github.fge.lambdas.supplier.ThrowingSupplier; + +import spark.Request; +import spark.Response; +import spark.Service; + +public class MessageIdReindexingRoutes implements Routes { + private static final String MESSAGE_ID_PARAM = ":messageId"; + private static final String MESSAGE_PATH = BASE_PATH + "/messages/" + MESSAGE_ID_PARAM; + + private final TaskManager taskManager; + private final MessageId.Factory messageIdFactory; + private final MessageIdReIndexer reIndexer; + private final JsonTransformer jsonTransformer; + + @Inject + public MessageIdReindexingRoutes(TaskManager taskManager, MessageId.Factory messageIdFactory, MessageIdReIndexer reIndexer, JsonTransformer jsonTransformer) { + this.taskManager = taskManager; + this.messageIdFactory = messageIdFactory; + this.reIndexer = reIndexer; + this.jsonTransformer = jsonTransformer; + } + + @Override + public String getBasePath() { + return BASE_PATH; + } + + @Override + public void define(Service service) { + service.post(MESSAGE_PATH, this::reIndexMessage, jsonTransformer); + } + + private TaskIdDto reIndexMessage(Request request, Response response) { + return wrap(request, response, () -> reIndexer.reIndex(extractMessageId(request))); + } + + private MessageId extractMessageId(Request request) { + try { + return messageIdFactory.fromString(request.params(MESSAGE_ID_PARAM)); + } catch (Exception e) { + throw ErrorResponder.builder() + .statusCode(HttpStatus.BAD_REQUEST_400) + .type(ErrorResponder.ErrorType.INVALID_ARGUMENT) + .message("Error while parsing 'messageId'") + .cause(e) + .haltError(); + } + } + + private TaskIdDto wrap(Request request, Response response, ThrowingSupplier<Task> taskGenerator) { + ReIndexingRoutesUtil.enforceTaskParameter(request); + + Task task = taskGenerator.get(); + TaskId taskId = taskManager.submit(task); + return TaskIdDto.respond(response, taskId); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/54fcdf39/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReIndexingRoutesUtil.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReIndexingRoutesUtil.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReIndexingRoutesUtil.java new file mode 100644 index 0000000..c82f055 --- /dev/null +++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReIndexingRoutesUtil.java @@ -0,0 +1,38 @@ +/**************************************************************** + * 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 org.apache.james.webadmin.utils.ErrorResponder; +import org.eclipse.jetty.http.HttpStatus; + +import spark.Request; + +class ReIndexingRoutesUtil { + static void enforceTaskParameter(Request request) { + String task = request.queryParams("task"); + if (!"reIndex".equals(task)) { + throw ErrorResponder.builder() + .statusCode(HttpStatus.BAD_REQUEST_400) + .type(ErrorResponder.ErrorType.INVALID_ARGUMENT) + .message("task query parameter is mandatory. The only supported value is `reIndex`") + .haltError(); + } + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/54fcdf39/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReindexingRoutes.java ---------------------------------------------------------------------- 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 b9c67c5..e042580 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 @@ -58,7 +58,7 @@ import spark.Service; @Path("/mailboxIndex") @Produces("application/json") public class ReindexingRoutes implements Routes { - private static final String BASE_PATH = "/mailboxIndex"; + static final String BASE_PATH = "/mailboxIndex"; private static final String USER_PARAM = ":user"; private static final String MAILBOX_PARAM = ":mailbox"; private static final String UID_PARAM = ":uid"; @@ -227,7 +227,7 @@ public class ReindexingRoutes implements Routes { } private TaskIdDto wrap(Request request, Response response, ThrowingSupplier<Task> taskGenerator) { - enforceTaskParameter(request); + ReIndexingRoutesUtil.enforceTaskParameter(request); Task task = taskGenerator.get(); TaskId taskId = taskManager.submit(task); return TaskIdDto.respond(response, taskId); @@ -289,15 +289,4 @@ public class ReindexingRoutes implements Routes { .haltError(); } } - - private void enforceTaskParameter(Request request) { - String task = request.queryParams("task"); - if (!"reIndex".equals(task)) { - throw ErrorResponder.builder() - .statusCode(HttpStatus.BAD_REQUEST_400) - .type(ErrorResponder.ErrorType.INVALID_ARGUMENT) - .message("task query parameter is mandatory. The only supported value is `reIndex`") - .haltError(); - } - } } http://git-wip-us.apache.org/repos/asf/james-project/blob/54fcdf39/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/ReindexingRoutesTest.java ---------------------------------------------------------------------- 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/ReindexingRoutesTest.java index dd20ca6..c0e90cf 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/ReindexingRoutesTest.java @@ -37,6 +37,7 @@ import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver; 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.MailboxId; @@ -51,6 +52,7 @@ 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.FullReindexingTask; +import org.apache.mailbox.tools.indexer.MessageIdReIndexerImpl; import org.apache.mailbox.tools.indexer.ReIndexerImpl; import org.apache.mailbox.tools.indexer.ReIndexerPerformer; import org.apache.mailbox.tools.indexer.SingleMailboxReindexingTask; @@ -94,6 +96,10 @@ class ReindexingRoutesTest { mailboxManager, mailboxIdFactory, reIndexer, + jsonTransformer), + new MessageIdReindexingRoutes(taskManager, + new InMemoryMessageId.Factory(), + new MessageIdReIndexerImpl(mailboxManager, mailboxManager.getMapperFactory(), searchIndex), jsonTransformer)); webAdminServer.configure(NO_CONFIGURATION); webAdminServer.await(); @@ -716,4 +722,132 @@ class ReindexingRoutesTest { } } + @Nested + class MessageIdReprocessing { + @Nested + class Validation { + @Test + void messageIdReprocessingShouldFailWithNoTask() { + when() + .post("/mailboxIndex/messages/7") + .then() + .statusCode(HttpStatus.BAD_REQUEST_400) + .body("statusCode", is(400)) + .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType())) + .body("message", is("task query parameter is mandatory. The only supported value is `reIndex`")); + } + + @Test + void messageIdReprocessingShouldFailWithBadTask() { + when() + .post("/mailboxIndex/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("task query parameter is mandatory. The only supported value is `reIndex`")); + } + + @Test + void messageIdReprocessingShouldFailWithBadMessageId() { + when() + .post("/mailboxIndex/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("/mailboxIndex/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(MessageIdReIndexerImpl.MessageIdReIndexingTask.TYPE)) + .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("/mailboxIndex/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(MessageIdReIndexerImpl.MessageIdReIndexingTask.TYPE)) + .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("/mailboxIndex/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 --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org