From d6fd27477174ba0f24479fc4117cac2ec5f935ca Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 24 Aug 2015 16:33:22 -0400 Subject: [PATCH] Add HttpServer and Jetty/Tomcat/RxNetty implementations This is a refactoring of the existing "echo" integration test with the goal to make it easier to add further integration tests. The HttpServer abstraction is on the test source side for now. --- .../reactive/web/http/CountingHandler.java | 63 ------------- ....java => EchoHandlerIntegrationTests.java} | 51 +++++++--- .../reactive/web/http/HttpServer.java | 31 +++++++ .../reactive/web/http/HttpServerSupport.java | 45 +++++++++ .../reactive/web/http/JettyHttpServer.java | 90 ++++++++++++++++++ .../reactive/web/http/RxNettyHttpServer.java | 71 ++++++++++++++ .../reactive/web/http/TomcatHttpServer.java | 93 +++++++++++++++++++ .../HttpHandlerRxNettyIntegrationTests.java | 46 --------- .../HttpHandlerJettyIntegrationTests.java | 63 ------------- .../HttpHandlerTomcatIntegrationTests.java | 66 ------------- 10 files changed, 370 insertions(+), 249 deletions(-) delete mode 100644 spring-web-reactive/src/test/java/org/springframework/reactive/web/http/CountingHandler.java rename spring-web-reactive/src/test/java/org/springframework/reactive/web/http/{AbstractHttpHandlerIntegrationTestCase.java => EchoHandlerIntegrationTests.java} (65%) create mode 100644 spring-web-reactive/src/test/java/org/springframework/reactive/web/http/HttpServer.java create mode 100644 spring-web-reactive/src/test/java/org/springframework/reactive/web/http/HttpServerSupport.java create mode 100644 spring-web-reactive/src/test/java/org/springframework/reactive/web/http/JettyHttpServer.java create mode 100644 spring-web-reactive/src/test/java/org/springframework/reactive/web/http/RxNettyHttpServer.java create mode 100644 spring-web-reactive/src/test/java/org/springframework/reactive/web/http/TomcatHttpServer.java delete mode 100644 spring-web-reactive/src/test/java/org/springframework/reactive/web/http/rxnetty/HttpHandlerRxNettyIntegrationTests.java delete mode 100644 spring-web-reactive/src/test/java/org/springframework/reactive/web/http/servlet/HttpHandlerJettyIntegrationTests.java delete mode 100644 spring-web-reactive/src/test/java/org/springframework/reactive/web/http/servlet/HttpHandlerTomcatIntegrationTests.java diff --git a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/CountingHandler.java b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/CountingHandler.java deleted file mode 100644 index f25c994072e..00000000000 --- a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/CountingHandler.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2002-2015 the original author or authors. - * - * Licensed 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.springframework.reactive.web.http; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; - -/** - * @author Arjen Poutsma - */ -public class CountingHandler implements ServerHttpHandler { - - private static final Log logger = LogFactory.getLog(CountingHandler.class); - - @Override - public Publisher handle(ServerHttpRequest request, ServerHttpResponse response) { - request.getBody().subscribe(new Subscriber() { - private Subscription subscription; - - private int byteCount = 0; - - @Override - public void onSubscribe(Subscription s) { - this.subscription = s; - this.subscription.request(1); - } - - @Override - public void onNext(byte[] bytes) { - byteCount += bytes.length; - this.subscription.request(1); - } - - @Override - public void onError(Throwable t) { - logger.error("CountingHttpHandler Error", t); - } - - @Override - public void onComplete() { - logger.info("Processed " + byteCount + " bytes"); - } - }); - return null; - } -} diff --git a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/AbstractHttpHandlerIntegrationTestCase.java b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/EchoHandlerIntegrationTests.java similarity index 65% rename from spring-web-reactive/src/test/java/org/springframework/reactive/web/http/AbstractHttpHandlerIntegrationTestCase.java rename to spring-web-reactive/src/test/java/org/springframework/reactive/web/http/EchoHandlerIntegrationTests.java index ff3694992a5..2195eb5b3b5 100644 --- a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/AbstractHttpHandlerIntegrationTestCase.java +++ b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/EchoHandlerIntegrationTests.java @@ -19,7 +19,11 @@ package org.springframework.reactive.web.http; import java.net.URI; import java.util.Random; +import org.junit.After; +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; @@ -29,41 +33,67 @@ import org.springframework.web.client.RestTemplate; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -public abstract class AbstractHttpHandlerIntegrationTestCase { + +@RunWith(Parameterized.class) +public class EchoHandlerIntegrationTests { private static final int REQUEST_SIZE = 4096 * 3; - protected static int port = SocketUtils.findAvailableTcpPort(); + private static int port = SocketUtils.findAvailableTcpPort(); + + + @Parameterized.Parameter(0) + public HttpServer server; private Random rnd = new Random(); + @Parameterized.Parameters(name = "server [{0}]") + public static Object[][] arguments() { + return new Object[][] { + {new JettyHttpServer()}, + {new TomcatHttpServer()}, + {new RxNettyHttpServer()} + }; + } + + + @Before + public void setup() throws Exception { + this.server.setPort(port); + this.server.setHandler(new EchoHandler()); + this.server.afterPropertiesSet(); + this.server.start(); + } + + @After + public void tearDown() throws Exception { + this.server.stop(); + } + + @Test - public void bytes() throws Exception { + public void echoBytes() throws Exception { RestTemplate restTemplate = new RestTemplate(); byte[] body = randomBytes(); - RequestEntity request = RequestEntity.post(new URI(url())).body(body); + RequestEntity request = RequestEntity.post(new URI("http://localhost:" + port)).body(body); ResponseEntity response = restTemplate.exchange(request, byte[].class); assertArrayEquals(body, response.getBody()); } @Test - public void string() throws Exception { + public void echoString() throws Exception { RestTemplate restTemplate = new RestTemplate(); String body = randomString(); - RequestEntity request = RequestEntity.post(new URI(url())).body(body); + RequestEntity request = RequestEntity.post(new URI("http://localhost:" + port)).body(body); ResponseEntity response = restTemplate.exchange(request, String.class); assertEquals(body, response.getBody()); } - protected static String url() { - return "http://localhost:" + port + "/rx"; - } - private String randomString() { StringBuilder builder = new StringBuilder(); int i = 1; @@ -90,5 +120,4 @@ public abstract class AbstractHttpHandlerIntegrationTestCase { return buffer; } - } diff --git a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/HttpServer.java b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/HttpServer.java new file mode 100644 index 00000000000..5562ed03b5e --- /dev/null +++ b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/HttpServer.java @@ -0,0 +1,31 @@ +/* + * Copyright 2002-2015 the original author or authors. + * + * Licensed 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.springframework.reactive.web.http; + + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.Lifecycle; + +/** + * @author Rossen Stoyanchev + */ +public interface HttpServer extends InitializingBean, Lifecycle { + + void setPort(int port); + + void setHandler(ServerHttpHandler handler); + +} diff --git a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/HttpServerSupport.java b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/HttpServerSupport.java new file mode 100644 index 00000000000..e9887b46542 --- /dev/null +++ b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/HttpServerSupport.java @@ -0,0 +1,45 @@ +/* + * Copyright 2002-2015 the original author or authors. + * + * Licensed 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.springframework.reactive.web.http; + + +/** + * @author Rossen Stoyanchev + */ +public class HttpServerSupport { + + private int port = -1; + + private ServerHttpHandler httpHandler; + + + public void setPort(int port) { + this.port = port; + } + + public int getPort() { + return this.port; + } + + public void setHandler(ServerHttpHandler handler) { + this.httpHandler = handler; + } + + public ServerHttpHandler getHttpHandler() { + return this.httpHandler; + } + +} diff --git a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/JettyHttpServer.java b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/JettyHttpServer.java new file mode 100644 index 00000000000..f2f45e6248e --- /dev/null +++ b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/JettyHttpServer.java @@ -0,0 +1,90 @@ +/* + * Copyright 2002-2015 the original author or authors. + * + * Licensed 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.springframework.reactive.web.http; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.reactive.web.http.servlet.HttpHandlerServlet; +import org.springframework.util.SocketUtils; + +/** + * @author Rossen Stoyanchev + */ +public class JettyHttpServer extends HttpServerSupport implements InitializingBean, HttpServer { + + private Server jettyServer; + + private boolean running; + + + @Override + public boolean isRunning() { + return this.running; + } + + @Override + public void afterPropertiesSet() throws Exception { + + if (getPort() == -1) { + setPort(SocketUtils.findAvailableTcpPort(8080)); + } + + this.jettyServer = new Server(); + + HttpHandlerServlet servlet = new HttpHandlerServlet(); + servlet.setHandler(new EchoHandler()); + ServletHolder servletHolder = new ServletHolder(servlet); + + ServletContextHandler contextHandler = new ServletContextHandler(this.jettyServer, "", false, false); + contextHandler.addServlet(servletHolder, "/"); + + ServerConnector connector = new ServerConnector(this.jettyServer); + connector.setPort(getPort()); + this.jettyServer.addConnector(connector); + } + + @Override + public void start() { + if (!this.running) { + try { + this.running = true; + this.jettyServer.start(); + } + catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + } + + @Override + public void stop() { + if (this.running) { + try { + this.running = false; + jettyServer.stop(); + jettyServer.destroy(); + } + catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + } + +} diff --git a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/RxNettyHttpServer.java b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/RxNettyHttpServer.java new file mode 100644 index 00000000000..d3eb174c03c --- /dev/null +++ b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/RxNettyHttpServer.java @@ -0,0 +1,71 @@ +/* + * Copyright 2002-2015 the original author or authors. + * + * Licensed 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.springframework.reactive.web.http; + +import io.netty.buffer.ByteBuf; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.reactive.web.http.rxnetty.RequestHandlerAdapter; +import org.springframework.util.Assert; + + +/** + * @author Rossen Stoyanchev + */ +public class RxNettyHttpServer extends HttpServerSupport implements InitializingBean, HttpServer { + + private RequestHandlerAdapter rxNettyHandler; + + private io.reactivex.netty.protocol.http.server.HttpServer rxNettyServer; + + private boolean running; + + + @Override + public boolean isRunning() { + return this.running; + } + + + @Override + public void afterPropertiesSet() throws Exception { + + Assert.notNull(getHttpHandler()); + this.rxNettyHandler = new RequestHandlerAdapter(getHttpHandler()); + + this.rxNettyServer = (getPort() != -1 ? + io.reactivex.netty.protocol.http.server.HttpServer.newServer(getPort()) : + io.reactivex.netty.protocol.http.server.HttpServer.newServer()); + } + + + @Override + public void start() { + if (!this.running) { + this.running = true; + this.rxNettyServer.start(this.rxNettyHandler); + } + } + + @Override + public void stop() { + if (this.running) { + this.running = false; + this.rxNettyServer.shutdown(); + } + } + +} diff --git a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/TomcatHttpServer.java b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/TomcatHttpServer.java new file mode 100644 index 00000000000..18716d4e975 --- /dev/null +++ b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/TomcatHttpServer.java @@ -0,0 +1,93 @@ +/* + * Copyright 2002-2015 the original author or authors. + * + * Licensed 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.springframework.reactive.web.http; + +import java.io.File; + +import org.apache.catalina.Context; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.startup.Tomcat; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.reactive.web.http.servlet.HttpHandlerServlet; +import org.springframework.util.Assert; +import org.springframework.util.SocketUtils; + + +/** + * @author Rossen Stoyanchev + */ +public class TomcatHttpServer extends HttpServerSupport implements InitializingBean, HttpServer { + + private Tomcat tomcatServer; + + private boolean running; + + + @Override + public boolean isRunning() { + return this.running; + } + + @Override + public void afterPropertiesSet() throws Exception { + + if (getPort() == -1) { + setPort(SocketUtils.findAvailableTcpPort(8080)); + } + + this.tomcatServer = new Tomcat(); + this.tomcatServer.setPort(getPort()); + + Assert.notNull(getHttpHandler()); + HttpHandlerServlet servlet = new HttpHandlerServlet(); + servlet.setHandler(getHttpHandler()); + + File base = new File(System.getProperty("java.io.tmpdir")); + Context rootContext = tomcatServer.addContext("", base.getAbsolutePath()); + Tomcat.addServlet(rootContext, "httpHandlerServlet", servlet); + rootContext.addServletMapping("/", "httpHandlerServlet"); + } + + + @Override + public void start() { + if (!this.running) { + try { + this.running = true; + this.tomcatServer.start(); + } + catch (LifecycleException ex) { + throw new IllegalStateException(ex); + } + } + } + + @Override + public void stop() { + if (this.running) { + try { + this.running = false; + this.tomcatServer.stop(); + this.tomcatServer.destroy(); + } + catch (LifecycleException ex) { + throw new IllegalStateException(ex); + } + } + } + +} diff --git a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/rxnetty/HttpHandlerRxNettyIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/rxnetty/HttpHandlerRxNettyIntegrationTests.java deleted file mode 100644 index 8cd0276f22e..00000000000 --- a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/rxnetty/HttpHandlerRxNettyIntegrationTests.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2002-2015 the original author or authors. - * - * Licensed 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.springframework.reactive.web.http.rxnetty; - -import io.netty.buffer.ByteBuf; -import io.reactivex.netty.protocol.http.server.HttpServer; -import org.junit.AfterClass; -import org.junit.BeforeClass; - -import org.springframework.reactive.web.http.EchoHandler; -import org.springframework.reactive.web.http.AbstractHttpHandlerIntegrationTestCase; - -/** - * @author Rossen Stoyanchev - */ -public class HttpHandlerRxNettyIntegrationTests extends AbstractHttpHandlerIntegrationTestCase { - - private static HttpServer httpServer; - - - @BeforeClass - public static void startServer() throws Exception { - RequestHandlerAdapter requestHandler = new RequestHandlerAdapter(new EchoHandler()); - httpServer = HttpServer.newServer(port); - httpServer.start(requestHandler::handle); - } - - @AfterClass - public static void stopServer() throws Exception { - httpServer.shutdown(); - } - -} \ No newline at end of file diff --git a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/servlet/HttpHandlerJettyIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/servlet/HttpHandlerJettyIntegrationTests.java deleted file mode 100644 index f68c4eef8a1..00000000000 --- a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/servlet/HttpHandlerJettyIntegrationTests.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2002-2015 the original author or authors. - * - * Licensed 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.springframework.reactive.web.http.servlet; - -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.junit.AfterClass; -import org.junit.BeforeClass; - -import org.springframework.reactive.web.http.AbstractHttpHandlerIntegrationTestCase; -import org.springframework.reactive.web.http.EchoHandler; - -/** - * @author Arjen Poutsma - */ -public class HttpHandlerJettyIntegrationTests - extends AbstractHttpHandlerIntegrationTestCase { - - private static Server jettyServer; - - @BeforeClass - public static void startServer() throws Exception { - jettyServer = new Server(); - ServerConnector connector = new ServerConnector(jettyServer); - connector.setPort(port); - ServletContextHandler handler = new ServletContextHandler(jettyServer, "", false, false); - HttpHandlerServlet servlet = new HttpHandlerServlet(); - servlet.setHandler(new EchoHandler()); - ServletHolder servletHolder = new ServletHolder(servlet); - handler.addServlet(servletHolder, "/rx"); - jettyServer.addConnector(connector); - jettyServer.start(); - } - - @AfterClass - public static void stopServer() throws Exception { - jettyServer.stop(); - jettyServer.destroy(); - } - - public static void main(String[] args) throws Exception { - startServer(); - System.out.println("Jetty running at: " + url()); - - } - -} \ No newline at end of file diff --git a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/servlet/HttpHandlerTomcatIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/servlet/HttpHandlerTomcatIntegrationTests.java deleted file mode 100644 index 9c8bb0b6d7c..00000000000 --- a/spring-web-reactive/src/test/java/org/springframework/reactive/web/http/servlet/HttpHandlerTomcatIntegrationTests.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2002-2015 the original author or authors. - * - * Licensed 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.springframework.reactive.web.http.servlet; - -import java.io.File; - -import org.apache.catalina.Context; -import org.apache.catalina.LifecycleException; -import org.apache.catalina.startup.Tomcat; -import org.junit.AfterClass; -import org.junit.BeforeClass; - -import org.springframework.reactive.web.http.AbstractHttpHandlerIntegrationTestCase; -import org.springframework.reactive.web.http.EchoHandler; - -/** - * @author Arjen Poutsma - */ -public class HttpHandlerTomcatIntegrationTests extends AbstractHttpHandlerIntegrationTestCase { - - private static Tomcat tomcatServer; - - - @BeforeClass - public static void startServer() throws LifecycleException, InterruptedException { - tomcatServer = new Tomcat(); - tomcatServer.setPort(port); - File base = new File(System.getProperty("java.io.tmpdir")); - Context rootCtx = tomcatServer.addContext("", base.getAbsolutePath()); - - HttpHandlerServlet servlet = new HttpHandlerServlet(); - servlet.setHandler(new EchoHandler()); - - Tomcat.addServlet(rootCtx, "handlerServlet", servlet); - rootCtx.addServletMapping("/rx", "handlerServlet"); - - tomcatServer.start(); - } - - @AfterClass - public static void stopServer() throws Exception { - tomcatServer.stop(); - tomcatServer.destroy(); - } - - public static void main(String[] args) throws Exception { - startServer(); - System.out.println("Tomcat running at: " + url()); - tomcatServer.getServer().await(); - } - -} \ No newline at end of file