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 2020/03/24 02:03:57 UTC
[james-project] 01/05: JAMES-3078 Migrate mock SMTP to reactor-netty
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 e784cd945c9beff94776c6174bd6d9a6595e4013
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Sat Mar 21 11:01:36 2020 +0700
JAMES-3078 Migrate mock SMTP to reactor-netty
---
server/mailet/mock-smtp-server/pom.xml | 8 +-
.../mock/smtp/server/HTTPConfigurationServer.java | 186 ++++++++++++---------
.../mock/smtp/server/ConfigurationClientTest.java | 4 +-
.../smtp/server/HTTPConfigurationServerTest.java | 19 +--
4 files changed, 121 insertions(+), 96 deletions(-)
diff --git a/server/mailet/mock-smtp-server/pom.xml b/server/mailet/mock-smtp-server/pom.xml
index 14c00b3..2c59171 100644
--- a/server/mailet/mock-smtp-server/pom.xml
+++ b/server/mailet/mock-smtp-server/pom.xml
@@ -43,10 +43,6 @@
</dependency>
<dependency>
<groupId>${james.groupId}</groupId>
- <artifactId>james-server-jetty</artifactId>
- </dependency>
- <dependency>
- <groupId>${james.groupId}</groupId>
<artifactId>james-server-util</artifactId>
</dependency>
<dependency>
@@ -86,6 +82,10 @@
<artifactId>feign-slf4j</artifactId>
</dependency>
<dependency>
+ <groupId>io.projectreactor.netty</groupId>
+ <artifactId>reactor-netty</artifactId>
+ </dependency>
+ <dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
diff --git a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/HTTPConfigurationServer.java b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/HTTPConfigurationServer.java
index 83f6ac0..32f7746 100644
--- a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/HTTPConfigurationServer.java
+++ b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/HTTPConfigurationServer.java
@@ -19,105 +19,78 @@
package org.apache.james.mock.smtp.server;
-import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
-import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
-import static javax.servlet.http.HttpServletResponse.SC_OK;
+import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
+import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
+import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR;
+import static io.netty.handler.codec.http.HttpResponseStatus.NO_CONTENT;
+import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import java.io.IOException;
+import java.util.Optional;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.james.http.jetty.Configuration;
-import org.apache.james.http.jetty.JettyHttpServer;
import org.apache.james.mock.smtp.server.jackson.MailAddressModule;
import org.apache.james.mock.smtp.server.model.Mails;
import org.apache.james.mock.smtp.server.model.MockSMTPBehaviorInformation;
import org.apache.james.mock.smtp.server.model.MockSmtpBehaviors;
import org.apache.james.util.Port;
+import org.reactivestreams.Publisher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.github.steveash.guavate.Guavate;
-public class HTTPConfigurationServer {
-
- public static class RunningStage {
- private final HTTPConfigurationServer underlyingServer;
-
- private RunningStage(HTTPConfigurationServer underlyingServer) {
- this.underlyingServer = underlyingServer;
- }
-
- public Port getPort() {
- return underlyingServer.getPort();
- }
+import reactor.core.publisher.Mono;
+import reactor.netty.DisposableServer;
+import reactor.netty.http.server.HttpServer;
+import reactor.netty.http.server.HttpServerRequest;
+import reactor.netty.http.server.HttpServerResponse;
- public void stop() throws Exception {
- underlyingServer.stop();
- }
- }
+public class HTTPConfigurationServer {
- static class SMTPBehaviorsServlet extends HttpServlet {
- private final SMTPBehaviorRepository smtpBehaviorRepository;
+ public static final String APPLICATION_JSON = "application/json";
- SMTPBehaviorsServlet(SMTPBehaviorRepository smtpBehaviorRepository) {
- this.smtpBehaviorRepository = smtpBehaviorRepository;
+ public static class Configuration {
+ static Configuration port(Port port) {
+ return new Configuration(Optional.of(port));
}
- @Override
- protected void doPut(HttpServletRequest req, HttpServletResponse resp) {
- try {
- MockSmtpBehaviors behaviors = OBJECT_MAPPER.readValue(req.getInputStream(), MockSmtpBehaviors.class);
- smtpBehaviorRepository.setBehaviors(behaviors);
- resp.setStatus(SC_NO_CONTENT);
- } catch (IOException e) {
- resp.setStatus(SC_BAD_REQUEST);
- }
+ static Configuration randomPort() {
+ return new Configuration(Optional.empty());
}
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
- MockSmtpBehaviors mockSmtpBehaviors = new MockSmtpBehaviors(smtpBehaviorRepository.remainingBehaviors()
- .map(MockSMTPBehaviorInformation::getBehavior)
- .collect(Guavate.toImmutableList()));
+ private final Optional<Port> port;
- resp.setStatus(SC_OK);
- resp.setContentType("application/json");
- OBJECT_MAPPER.writeValue(resp.getOutputStream(), mockSmtpBehaviors);
+ Configuration(Optional<Port> port) {
+ this.port = port;
}
- @Override
- protected void doDelete(HttpServletRequest req, HttpServletResponse resp) {
- smtpBehaviorRepository.clearBehaviors();
- resp.setStatus(SC_NO_CONTENT);
+ Optional<Port> getPort() {
+ return port;
}
}
- static class SMTPMailsServlet extends HttpServlet {
- private final ReceivedMailRepository receivedMailRepository;
+ public static class RunningStage {
+ private final DisposableServer server;
- SMTPMailsServlet(ReceivedMailRepository receivedMailRepository) {
- this.receivedMailRepository = receivedMailRepository;
+ private RunningStage(DisposableServer server) {
+ this.server = server;
}
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
- Mails mails = new Mails(receivedMailRepository.list());
- resp.setStatus(SC_OK);
- resp.setContentType("application/json");
- OBJECT_MAPPER.writeValue(resp.getOutputStream(), mails);
+ public Port getPort() {
+ return Port.of(server.port());
}
- @Override
- protected void doDelete(HttpServletRequest req, HttpServletResponse resp) {
- receivedMailRepository.clear();
- resp.setStatus(SC_NO_CONTENT);
+ public void stop() {
+ server.disposeNow();
}
}
+ private static final Logger LOGGER = LoggerFactory.getLogger(HTTPConfigurationServer.class);
+ private static final int RANDOM_PORT = 0;
static final String SMTP_BEHAVIORS = "/smtpBehaviors";
static final String SMTP_MAILS = "/smtpMails";
@@ -129,35 +102,88 @@ public class HTTPConfigurationServer {
public static HTTPConfigurationServer onRandomPort(SMTPBehaviorRepository smtpBehaviorRepository, ReceivedMailRepository receivedMailRepository) {
return new HTTPConfigurationServer(smtpBehaviorRepository,
receivedMailRepository,
- Configuration.builder().randomPort());
+ Configuration.randomPort());
}
public static HTTPConfigurationServer onPort(SMTPBehaviorRepository smtpBehaviorRepository, ReceivedMailRepository receivedMailRepository, Port port) {
return new HTTPConfigurationServer(smtpBehaviorRepository,
receivedMailRepository,
- Configuration.builder().port(port.getValue()));
+ Configuration.port(port));
}
- private final JettyHttpServer jettyHttpServer;
+ private final SMTPBehaviorRepository smtpBehaviorRepository;
+ private final ReceivedMailRepository receivedMailRepository;
+ private final Configuration configuration;
+
+ private HTTPConfigurationServer(SMTPBehaviorRepository smtpBehaviorRepository, ReceivedMailRepository receivedMailRepository, Configuration configuration) {
+ this.smtpBehaviorRepository = smtpBehaviorRepository;
+ this.receivedMailRepository = receivedMailRepository;
+ this.configuration = configuration;
+ }
- private HTTPConfigurationServer(SMTPBehaviorRepository smtpBehaviorRepository, ReceivedMailRepository receivedMailRepository, Configuration.Builder configurationBuilder) {
- jettyHttpServer = JettyHttpServer.create(configurationBuilder.serve(SMTP_BEHAVIORS)
- .with(new SMTPBehaviorsServlet(smtpBehaviorRepository))
- .serve(SMTP_MAILS)
- .with(new SMTPMailsServlet(receivedMailRepository))
- .build());
+ public RunningStage start() {
+ return new RunningStage(HttpServer.create()
+ .port(configuration.getPort()
+ .map(Port::getValue)
+ .orElse(RANDOM_PORT))
+ .route(routes -> routes
+ .get(SMTP_BEHAVIORS, this::getBehaviors)
+ .put(SMTP_BEHAVIORS, this::putBehaviors)
+ .delete(SMTP_BEHAVIORS, this::deleteBehaviors)
+ .get(SMTP_MAILS, this::getMails)
+ .delete(SMTP_MAILS, this::deleteMails))
+ .bindNow());
}
- public RunningStage start() throws Exception {
- jettyHttpServer.start();
- return new RunningStage(this);
+ private Publisher<Void> getBehaviors(HttpServerRequest req, HttpServerResponse res) {
+ MockSmtpBehaviors mockSmtpBehaviors = new MockSmtpBehaviors(smtpBehaviorRepository.remainingBehaviors()
+ .map(MockSMTPBehaviorInformation::getBehavior)
+ .collect(Guavate.toImmutableList()));
+
+ try {
+ return res.status(OK)
+ .header(CONTENT_TYPE, APPLICATION_JSON)
+ .sendString(Mono.just(OBJECT_MAPPER.writeValueAsString(mockSmtpBehaviors)));
+ } catch (JsonProcessingException e) {
+ LOGGER.error("Could not serialize JSON", e);
+ return res.status(INTERNAL_SERVER_ERROR).send();
+ }
}
- private Port getPort() {
- return new Port(jettyHttpServer.getPort());
+ private Publisher<Void> putBehaviors(HttpServerRequest req, HttpServerResponse res) {
+ return req.receive().aggregate().asInputStream()
+ .flatMap(inputStream -> {
+ try {
+ MockSmtpBehaviors behaviors = OBJECT_MAPPER.readValue(inputStream, MockSmtpBehaviors.class);
+ smtpBehaviorRepository.setBehaviors(behaviors);
+ return res.status(NO_CONTENT).send();
+ } catch (IOException e) {
+ LOGGER.info("Bad request", e);
+ return res.status(BAD_REQUEST).send();
+ }
+ });
}
- private void stop() throws Exception {
- jettyHttpServer.stop();
+ private Publisher<Void> deleteBehaviors(HttpServerRequest req, HttpServerResponse res) {
+ smtpBehaviorRepository.clearBehaviors();
+ return res.status(NO_CONTENT).send();
+ }
+
+ private Publisher<Void> deleteMails(HttpServerRequest req, HttpServerResponse res) {
+ receivedMailRepository.clear();
+ return res.status(NO_CONTENT).send();
+ }
+
+ private Publisher<Void> getMails(HttpServerRequest req, HttpServerResponse res) {
+ Mails mails = new Mails(receivedMailRepository.list());
+
+ try {
+ return res.status(OK)
+ .header(CONTENT_TYPE, APPLICATION_JSON)
+ .sendString(Mono.just(OBJECT_MAPPER.writeValueAsString(mails)));
+ } catch (JsonProcessingException e) {
+ LOGGER.error("Could not serialize JSON", e);
+ return res.status(INTERNAL_SERVER_ERROR).send();
+ }
}
}
diff --git a/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/ConfigurationClientTest.java b/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/ConfigurationClientTest.java
index c1d9c1f..ae1bdc3 100644
--- a/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/ConfigurationClientTest.java
+++ b/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/ConfigurationClientTest.java
@@ -34,7 +34,7 @@ class ConfigurationClientTest {
private ReceivedMailRepository mailRepository;
@BeforeEach
- void setUp() throws Exception {
+ void setUp() {
behaviorRepository = new SMTPBehaviorRepository();
mailRepository = new ReceivedMailRepository();
server = HTTPConfigurationServer.onRandomPort(behaviorRepository, mailRepository)
@@ -44,7 +44,7 @@ class ConfigurationClientTest {
}
@AfterEach
- void tearDown() throws Exception {
+ void tearDown() {
server.stop();
}
diff --git a/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/HTTPConfigurationServerTest.java b/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/HTTPConfigurationServerTest.java
index 4cc18aa..962f1c8 100644
--- a/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/HTTPConfigurationServerTest.java
+++ b/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/HTTPConfigurationServerTest.java
@@ -24,8 +24,8 @@ import static io.restassured.RestAssured.when;
import static io.restassured.RestAssured.with;
import static io.restassured.config.EncoderConfig.encoderConfig;
import static io.restassured.config.RestAssuredConfig.newConfig;
-import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
+import static io.netty.handler.codec.http.HttpResponseStatus.NO_CONTENT;
import static org.apache.james.mock.smtp.server.Fixture.JSON_BEHAVIORS;
import static org.apache.james.mock.smtp.server.Fixture.JSON_MAIL;
import static org.apache.james.mock.smtp.server.Fixture.JSON_MAILS_LIST;
@@ -34,7 +34,6 @@ import static org.hamcrest.Matchers.hasSize;
import java.nio.charset.StandardCharsets;
import org.apache.james.mock.smtp.server.Fixture.MailsFixutre;
-import org.eclipse.jetty.http.HttpStatus;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
@@ -52,7 +51,7 @@ class HTTPConfigurationServerTest {
@Nested
class SMTPBehaviorsTest {
@BeforeEach
- void setUp() throws Exception {
+ void setUp() {
server = HTTPConfigurationServer.onRandomPort(new SMTPBehaviorRepository(), new ReceivedMailRepository())
.start();
@@ -66,7 +65,7 @@ class HTTPConfigurationServerTest {
}
@AfterEach
- void tearDown() throws Exception {
+ void tearDown() {
server.stop();
}
@@ -115,7 +114,7 @@ class HTTPConfigurationServerTest {
.when()
.put()
.then()
- .statusCode(HttpStatus.NO_CONTENT_204);
+ .statusCode(NO_CONTENT.code());
}
@Test
@@ -127,7 +126,7 @@ class HTTPConfigurationServerTest {
.when()
.put()
.then()
- .statusCode(HttpStatus.NO_CONTENT_204);
+ .statusCode(NO_CONTENT.code());
}
@Test
@@ -135,7 +134,7 @@ class HTTPConfigurationServerTest {
when()
.delete()
.then()
- .statusCode(HttpStatus.NO_CONTENT_204);
+ .statusCode(NO_CONTENT.code());
}
}
@@ -144,7 +143,7 @@ class HTTPConfigurationServerTest {
private ReceivedMailRepository mailRepository;
@BeforeEach
- void setUp() throws Exception {
+ void setUp() {
mailRepository = new ReceivedMailRepository();
server = HTTPConfigurationServer.onRandomPort(new SMTPBehaviorRepository(), mailRepository)
@@ -160,7 +159,7 @@ class HTTPConfigurationServerTest {
}
@AfterEach
- void tearDown() throws Exception {
+ void tearDown() {
server.stop();
}
@@ -225,7 +224,7 @@ class HTTPConfigurationServerTest {
when()
.delete()
.then()
- .statusCode(SC_NO_CONTENT);
+ .statusCode(NO_CONTENT.code());
}
@Test
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org