Browse Source

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.
pull/1111/head
Rossen Stoyanchev 11 years ago
parent
commit
d6fd274771
  1. 63
      spring-web-reactive/src/test/java/org/springframework/reactive/web/http/CountingHandler.java
  2. 51
      spring-web-reactive/src/test/java/org/springframework/reactive/web/http/EchoHandlerIntegrationTests.java
  3. 31
      spring-web-reactive/src/test/java/org/springframework/reactive/web/http/HttpServer.java
  4. 45
      spring-web-reactive/src/test/java/org/springframework/reactive/web/http/HttpServerSupport.java
  5. 90
      spring-web-reactive/src/test/java/org/springframework/reactive/web/http/JettyHttpServer.java
  6. 71
      spring-web-reactive/src/test/java/org/springframework/reactive/web/http/RxNettyHttpServer.java
  7. 93
      spring-web-reactive/src/test/java/org/springframework/reactive/web/http/TomcatHttpServer.java
  8. 46
      spring-web-reactive/src/test/java/org/springframework/reactive/web/http/rxnetty/HttpHandlerRxNettyIntegrationTests.java
  9. 63
      spring-web-reactive/src/test/java/org/springframework/reactive/web/http/servlet/HttpHandlerJettyIntegrationTests.java
  10. 66
      spring-web-reactive/src/test/java/org/springframework/reactive/web/http/servlet/HttpHandlerTomcatIntegrationTests.java

63
spring-web-reactive/src/test/java/org/springframework/reactive/web/http/CountingHandler.java

@ -1,63 +0,0 @@ @@ -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<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
request.getBody().subscribe(new Subscriber<byte[]>() {
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;
}
}

51
spring-web-reactive/src/test/java/org/springframework/reactive/web/http/AbstractHttpHandlerIntegrationTestCase.java → spring-web-reactive/src/test/java/org/springframework/reactive/web/http/EchoHandlerIntegrationTests.java

@ -19,7 +19,11 @@ package org.springframework.reactive.web.http; @@ -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; @@ -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<byte[]> request = RequestEntity.post(new URI(url())).body(body);
RequestEntity<byte[]> request = RequestEntity.post(new URI("http://localhost:" + port)).body(body);
ResponseEntity<byte[]> 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<String> request = RequestEntity.post(new URI(url())).body(body);
RequestEntity<String> request = RequestEntity.post(new URI("http://localhost:" + port)).body(body);
ResponseEntity<String> 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 { @@ -90,5 +120,4 @@ public abstract class AbstractHttpHandlerIntegrationTestCase {
return buffer;
}
}

31
spring-web-reactive/src/test/java/org/springframework/reactive/web/http/HttpServer.java

@ -0,0 +1,31 @@ @@ -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);
}

45
spring-web-reactive/src/test/java/org/springframework/reactive/web/http/HttpServerSupport.java

@ -0,0 +1,45 @@ @@ -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;
}
}

90
spring-web-reactive/src/test/java/org/springframework/reactive/web/http/JettyHttpServer.java

@ -0,0 +1,90 @@ @@ -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);
}
}
}
}

71
spring-web-reactive/src/test/java/org/springframework/reactive/web/http/RxNettyHttpServer.java

@ -0,0 +1,71 @@ @@ -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<ByteBuf, ByteBuf> 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();
}
}
}

93
spring-web-reactive/src/test/java/org/springframework/reactive/web/http/TomcatHttpServer.java

@ -0,0 +1,93 @@ @@ -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);
}
}
}
}

46
spring-web-reactive/src/test/java/org/springframework/reactive/web/http/rxnetty/HttpHandlerRxNettyIntegrationTests.java

@ -1,46 +0,0 @@ @@ -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<ByteBuf, ByteBuf> 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();
}
}

63
spring-web-reactive/src/test/java/org/springframework/reactive/web/http/servlet/HttpHandlerJettyIntegrationTests.java

@ -1,63 +0,0 @@ @@ -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());
}
}

66
spring-web-reactive/src/test/java/org/springframework/reactive/web/http/servlet/HttpHandlerTomcatIntegrationTests.java

@ -1,66 +0,0 @@ @@ -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();
}
}
Loading…
Cancel
Save